PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/wordpress/wp-content/plugins/woocommerce/woocommerce-core-functions.php

https://github.com/hurricane-voronin/eshop
PHP | 2466 lines | 1271 code | 449 blank | 746 comment | 221 complexity | 62da0b0e2b928f8efc466cb5401497b6 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, AGPL-1.0, LGPL-2.1

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

  1. <?php
  2. /**
  3. * WooCommerce Core Functions
  4. *
  5. * Functions available on both the front-end and admin.
  6. *
  7. * @author WooThemes
  8. * @category Core
  9. * @package WooCommerce/Functions
  10. * @version 1.6.4
  11. */
  12. if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
  13. /**
  14. * Hooks used in admin and frontend
  15. */
  16. add_filter( 'woocommerce_coupon_code', 'sanitize_text_field' );
  17. add_filter( 'woocommerce_coupon_code', 'strtolower' ); // Coupons case-insensitive by default
  18. add_filter( 'woocommerce_stock_amount', 'intval' ); // Stock amounts are integers by default
  19. /**
  20. * Main function for returning products, uses the WC_Product_Factory class.
  21. *
  22. * @access public
  23. * @param mixed $the_product Post object or post ID of the product.
  24. * @param array $args (default: array()) Contains all arguments to be used to get this product.
  25. * @return void
  26. */
  27. function get_product( $the_product = false, $args = array() ) {
  28. global $woocommerce;
  29. return $woocommerce->product_factory->get_product( $the_product, $args );
  30. }
  31. /**
  32. * Function that returns an array containing the IDs of the products that are on sale.
  33. *
  34. * @since 2.0
  35. * @access public
  36. * @return array
  37. */
  38. function woocommerce_get_product_ids_on_sale() {
  39. // Load from cache
  40. $product_ids_on_sale = get_transient( 'wc_products_onsale' );
  41. // Valid cache found
  42. if ( false !== $product_ids_on_sale )
  43. return $product_ids_on_sale;
  44. $on_sale = get_posts( array(
  45. 'post_type' => array( 'product', 'product_variation' ),
  46. 'posts_per_page' => -1,
  47. 'post_status' => 'publish',
  48. 'meta_query' => array(
  49. array(
  50. 'key' => '_sale_price',
  51. 'value' => 0,
  52. 'compare' => '>=',
  53. 'type' => 'DECIMAL',
  54. ),
  55. array(
  56. 'key' => '_sale_price',
  57. 'value' => '',
  58. 'compare' => '!=',
  59. 'type' => '',
  60. )
  61. ),
  62. 'fields' => 'id=>parent',
  63. ) );
  64. $product_ids = array_keys( $on_sale );
  65. $parent_ids = array_values( $on_sale );
  66. // Check for scheduled sales which have not started
  67. foreach ( $product_ids as $key => $id ) {
  68. if ( get_post_meta( $id, '_sale_price_dates_from', true ) > current_time( 'timestamp' ) ) {
  69. unset( $product_ids[ $key ] );
  70. }
  71. }
  72. $product_ids_on_sale = array_unique( array_merge( $product_ids, $parent_ids ) );
  73. set_transient( 'wc_products_onsale', $product_ids_on_sale );
  74. return $product_ids_on_sale;
  75. }
  76. /**
  77. * woocommerce_sanitize_taxonomy_name function.
  78. *
  79. * @access public
  80. * @param mixed $taxonomy
  81. * @return void
  82. */
  83. function woocommerce_sanitize_taxonomy_name( $taxonomy ) {
  84. return str_replace( array( ' ', '_' ), '-', strtolower( $taxonomy ) );
  85. }
  86. /**
  87. * woocommerce_get_attachment_image_attributes function.
  88. *
  89. * @access public
  90. * @param mixed $attr
  91. * @return void
  92. */
  93. function woocommerce_get_attachment_image_attributes( $attr ) {
  94. if ( strstr( $attr['src'], 'woocommerce_uploads/' ) )
  95. $attr['src'] = woocommerce_placeholder_img_src();
  96. return $attr;
  97. }
  98. add_filter( 'wp_get_attachment_image_attributes', 'woocommerce_get_attachment_image_attributes' );
  99. /**
  100. * woocommerce_prepare_attachment_for_js function.
  101. *
  102. * @access public
  103. * @param mixed $response
  104. * @return void
  105. */
  106. function woocommerce_prepare_attachment_for_js( $response ) {
  107. if ( isset( $response['url'] ) && strstr( $response['url'], 'woocommerce_uploads/' ) ) {
  108. $response['full']['url'] = woocommerce_placeholder_img_src();
  109. if ( isset( $response['sizes'] ) ) {
  110. foreach( $response['sizes'] as $size => $value ) {
  111. $response['sizes'][ $size ]['url'] = woocommerce_placeholder_img_src();
  112. }
  113. }
  114. }
  115. return $response;
  116. }
  117. add_filter( 'wp_prepare_attachment_for_js', 'woocommerce_prepare_attachment_for_js' );
  118. /**
  119. * woocommerce_get_dimension function.
  120. *
  121. * Normalise dimensions, unify to cm then convert to wanted unit value
  122. *
  123. * Usage: woocommerce_get_dimension(55, 'in');
  124. *
  125. * @access public
  126. * @param mixed $dim
  127. * @param mixed $to_unit 'in', 'm', 'cm', 'm'
  128. * @return float
  129. */
  130. function woocommerce_get_dimension( $dim, $to_unit ) {
  131. $from_unit = strtolower( get_option( 'woocommerce_dimension_unit' ) );
  132. $to_unit = strtolower( $to_unit );
  133. // Unify all units to cm first
  134. if ( $from_unit !== $to_unit ) {
  135. switch ( $from_unit ) {
  136. case 'in':
  137. $dim *= 2.54;
  138. break;
  139. case 'm':
  140. $dim *= 100;
  141. break;
  142. case 'mm':
  143. $dim *= 0.1;
  144. break;
  145. case 'yd':
  146. $dim *= 0.010936133;
  147. break;
  148. }
  149. // Output desired unit
  150. switch ( $to_unit ) {
  151. case 'in':
  152. $dim *= 0.3937;
  153. break;
  154. case 'm':
  155. $dim *= 0.01;
  156. break;
  157. case 'mm':
  158. $dim *= 10;
  159. break;
  160. case 'yd':
  161. $dim *= 91.44;
  162. break;
  163. }
  164. }
  165. return ( $dim < 0 ) ? 0 : $dim;
  166. }
  167. /**
  168. * woocommerce_get_weight function.
  169. *
  170. * Normalise weights, unify to cm then convert to wanted unit value
  171. *
  172. * Usage: woocommerce_get_weight(55, 'kg');
  173. *
  174. * @access public
  175. * @param mixed $weight
  176. * @param mixed $to_unit 'g', 'kg', 'lbs'
  177. * @return float
  178. */
  179. function woocommerce_get_weight( $weight, $to_unit ) {
  180. $from_unit = strtolower( get_option('woocommerce_weight_unit') );
  181. $to_unit = strtolower( $to_unit );
  182. //Unify all units to kg first
  183. if ( $from_unit !== $to_unit ) {
  184. switch ( $from_unit ) {
  185. case 'g':
  186. $weight *= 0.001;
  187. break;
  188. case 'lbs':
  189. $weight *= 0.4536;
  190. break;
  191. case 'oz':
  192. $weight *= 0.0283;
  193. break;
  194. }
  195. // Output desired unit
  196. switch ( $to_unit ) {
  197. case 'g':
  198. $weight *= 1000;
  199. break;
  200. case 'lbs':
  201. $weight *= 2.2046;
  202. break;
  203. case 'oz':
  204. $weight *= 35.274;
  205. break;
  206. }
  207. }
  208. return ( $weight < 0 ) ? 0 : $weight;
  209. }
  210. /**
  211. * Get product name with extra details such as SKU price and attributes. Used within admin.
  212. *
  213. * @access public
  214. * @param mixed $product
  215. * @return void
  216. */
  217. function woocommerce_get_formatted_product_name( $product ) {
  218. if ( ! $product || ! is_object( $product ) )
  219. return;
  220. if ( $product->get_sku() )
  221. $identifier = $product->get_sku();
  222. elseif ( $product->is_type( 'variation' ) )
  223. $identifier = '#' . $product->variation_id;
  224. else
  225. $identifier = '#' . $product->id;
  226. if ( $product->is_type( 'variation' ) ) {
  227. $attributes = $product->get_variation_attributes();
  228. $extra_data = ' &ndash; ' . implode( ', ', $attributes ) . ' &ndash; ' . woocommerce_price( $product->get_price() );
  229. } else {
  230. $extra_data = '';
  231. }
  232. return sprintf( __( '%s &ndash; %s%s', 'woocommerce' ), $identifier, $product->get_title(), $extra_data );
  233. }
  234. /**
  235. * Get the placeholder image URL for products etc
  236. *
  237. * @access public
  238. * @return string
  239. */
  240. function woocommerce_placeholder_img_src() {
  241. global $woocommerce;
  242. return apply_filters('woocommerce_placeholder_img_src', $woocommerce->plugin_url() . '/assets/images/placeholder.png' );
  243. }
  244. /**
  245. * Get the placeholder image
  246. *
  247. * @access public
  248. * @return string
  249. */
  250. function woocommerce_placeholder_img( $size = 'shop_thumbnail' ) {
  251. global $woocommerce;
  252. $dimensions = $woocommerce->get_image_size( $size );
  253. return apply_filters('woocommerce_placeholder_img', '<img src="' . woocommerce_placeholder_img_src() . '" alt="Placeholder" width="' . $dimensions['width'] . '" height="' . $dimensions['height'] . '" />' );
  254. }
  255. /**
  256. * woocommerce_lostpassword_url function.
  257. *
  258. * @access public
  259. * @param mixed $url
  260. * @return void
  261. */
  262. function woocommerce_lostpassword_url( $url ) {
  263. $id = woocommerce_get_page_id( 'lost_password' );
  264. if ( $id != -1 )
  265. $url = get_permalink( $id );
  266. return $url;
  267. }
  268. add_filter( 'lostpassword_url', 'woocommerce_lostpassword_url' );
  269. /**
  270. * Send HTML emails from WooCommerce
  271. *
  272. * @access public
  273. * @param mixed $to
  274. * @param mixed $subject
  275. * @param mixed $message
  276. * @param string $headers (default: "Content-Type: text/html\r\n")
  277. * @param string $attachments (default: "")
  278. * @return void
  279. */
  280. function woocommerce_mail( $to, $subject, $message, $headers = "Content-Type: text/html\r\n", $attachments = "" ) {
  281. global $woocommerce;
  282. $mailer = $woocommerce->mailer();
  283. $mailer->send( $to, $subject, $message, $headers, $attachments );
  284. }
  285. if ( ! function_exists( 'woocommerce_get_page_id' ) ) {
  286. /**
  287. * WooCommerce page IDs
  288. *
  289. * retrieve page ids - used for myaccount, edit_address, change_password, shop, cart, checkout, pay, view_order, thanks, terms
  290. *
  291. * returns -1 if no page is found
  292. *
  293. * @access public
  294. * @param string $page
  295. * @return int
  296. */
  297. function woocommerce_get_page_id( $page ) {
  298. $page = apply_filters('woocommerce_get_' . $page . '_page_id', get_option('woocommerce_' . $page . '_page_id'));
  299. return ( $page ) ? $page : -1;
  300. }
  301. }
  302. if ( ! function_exists( 'woocommerce_empty_cart' ) ) {
  303. /**
  304. * WooCommerce clear cart
  305. *
  306. * Clears the cart session when called
  307. *
  308. * @access public
  309. * @return void
  310. */
  311. function woocommerce_empty_cart() {
  312. global $woocommerce;
  313. if ( ! isset( $woocommerce->cart ) || $woocommerce->cart == '' )
  314. $woocommerce->cart = new WC_Cart();
  315. $woocommerce->cart->empty_cart( false );
  316. }
  317. }
  318. if ( ! function_exists( 'woocommerce_disable_admin_bar' ) ) {
  319. /**
  320. * WooCommerce disable admin bar
  321. *
  322. * @access public
  323. * @param bool $show_admin_bar
  324. * @return bool
  325. */
  326. function woocommerce_disable_admin_bar( $show_admin_bar ) {
  327. if ( get_option('woocommerce_lock_down_admin')=='yes' && ! ( current_user_can('edit_posts') || current_user_can('manage_woocommerce') ) ) {
  328. $show_admin_bar = false;
  329. }
  330. return $show_admin_bar;
  331. }
  332. }
  333. /**
  334. * Load the cart upon login
  335. *
  336. * @access public
  337. * @param mixed $user_login
  338. * @param mixed $user
  339. * @return void
  340. */
  341. function woocommerce_load_persistent_cart( $user_login, $user ) {
  342. global $woocommerce;
  343. $saved_cart = get_user_meta( $user->ID, '_woocommerce_persistent_cart', true );
  344. if ( $saved_cart )
  345. if ( empty( $woocommerce->session->cart ) || ! is_array( $woocommerce->session->cart ) || sizeof( $woocommerce->session->cart ) == 0 )
  346. $woocommerce->session->cart = $saved_cart['cart'];
  347. }
  348. /**
  349. * is_woocommerce - Returns true if on a page which uses WooCommerce templates (cart and checkout are standard pages with shortcodes and thus are not included)
  350. *
  351. * @access public
  352. * @return bool
  353. */
  354. function is_woocommerce() {
  355. return ( is_shop() || is_product_category() || is_product_tag() || is_product() ) ? true : false;
  356. }
  357. if ( ! function_exists( 'is_shop' ) ) {
  358. /**
  359. * is_shop - Returns true when viewing the product type archive (shop).
  360. *
  361. * @access public
  362. * @return bool
  363. */
  364. function is_shop() {
  365. return ( is_post_type_archive( 'product' ) || is_page( woocommerce_get_page_id( 'shop' ) ) ) ? true : false;
  366. }
  367. }
  368. if ( ! function_exists( 'is_product_category' ) ) {
  369. /**
  370. * is_product_category - Returns true when viewing a product category.
  371. *
  372. * @access public
  373. * @param string $term (default: '') The term slug your checking for. Leave blank to return true on any.
  374. * @return bool
  375. */
  376. function is_product_category( $term = '' ) {
  377. return is_tax( 'product_cat', $term );
  378. }
  379. }
  380. if ( ! function_exists( 'is_product_tag' ) ) {
  381. /**
  382. * is_product_tag - Returns true when viewing a product tag.
  383. *
  384. * @access public
  385. * @param string $term (default: '') The term slug your checking for. Leave blank to return true on any.
  386. * @return bool
  387. */
  388. function is_product_tag( $term = '' ) {
  389. return is_tax( 'product_tag', $term );
  390. }
  391. }
  392. if ( ! function_exists( 'is_product' ) ) {
  393. /**
  394. * is_product - Returns true when viewing a single product.
  395. *
  396. * @access public
  397. * @return bool
  398. */
  399. function is_product() {
  400. return is_singular( array( 'product' ) );
  401. }
  402. }
  403. if ( ! function_exists( 'is_cart' ) ) {
  404. /**
  405. * is_cart - Returns true when viewing the cart page.
  406. *
  407. * @access public
  408. * @return bool
  409. */
  410. function is_cart() {
  411. return is_page( woocommerce_get_page_id( 'cart' ) );
  412. }
  413. }
  414. if ( ! function_exists( 'is_checkout' ) ) {
  415. /**
  416. * is_checkout - Returns true when viewing the checkout page.
  417. *
  418. * @access public
  419. * @return bool
  420. */
  421. function is_checkout() {
  422. return ( is_page( woocommerce_get_page_id( 'checkout' ) ) || is_page( woocommerce_get_page_id( 'pay' ) ) ) ? true : false;
  423. }
  424. }
  425. if ( ! function_exists( 'is_account_page' ) ) {
  426. /**
  427. * is_account_page - Returns true when viewing an account page.
  428. *
  429. * @access public
  430. * @return bool
  431. */
  432. function is_account_page() {
  433. return is_page( woocommerce_get_page_id( 'myaccount' ) ) || is_page( woocommerce_get_page_id( 'edit_address' ) ) || is_page( woocommerce_get_page_id( 'view_order' ) ) || is_page( woocommerce_get_page_id( 'change_password' ) ) || is_page( woocommerce_get_page_id( 'lost_password' ) ) || apply_filters( 'woocommerce_is_account_page', false ) ? true : false;
  434. }
  435. }
  436. if ( ! function_exists( 'is_order_received_page' ) ) {
  437. /**
  438. * is_order_received_page - Returns true when viewing the order received page.
  439. *
  440. * @access public
  441. * @return bool
  442. */
  443. function is_order_received_page() {
  444. return ( is_page( woocommerce_get_page_id( 'thanks' ) ) ) ? true : false;
  445. }
  446. }
  447. if ( ! function_exists( 'is_ajax' ) ) {
  448. /**
  449. * is_ajax - Returns true when the page is loaded via ajax.
  450. *
  451. * @access public
  452. * @return bool
  453. */
  454. function is_ajax() {
  455. if ( defined('DOING_AJAX') )
  456. return true;
  457. return ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) ? true : false;
  458. }
  459. }
  460. if ( ! function_exists( 'is_filtered' ) ) {
  461. /**
  462. * is_filtered - Returns true when filtering products using layered nav or price sliders.
  463. *
  464. * @access public
  465. * @return bool
  466. */
  467. function is_filtered() {
  468. global $_chosen_attributes;
  469. return ( sizeof( $_chosen_attributes ) > 0 || ( isset( $_GET['max_price'] ) && isset( $_GET['min_price'] ) ) ) ? true : false;
  470. }
  471. }
  472. /**
  473. * Get template part (for templates like the shop-loop).
  474. *
  475. * @access public
  476. * @param mixed $slug
  477. * @param string $name (default: '')
  478. * @return void
  479. */
  480. function woocommerce_get_template_part( $slug, $name = '' ) {
  481. global $woocommerce;
  482. $template = '';
  483. // Look in yourtheme/slug-name.php and yourtheme/woocommerce/slug-name.php
  484. if ( $name )
  485. $template = locate_template( array ( "{$slug}-{$name}.php", "{$woocommerce->template_url}{$slug}-{$name}.php" ) );
  486. // Get default slug-name.php
  487. if ( !$template && $name && file_exists( $woocommerce->plugin_path() . "/templates/{$slug}-{$name}.php" ) )
  488. $template = $woocommerce->plugin_path() . "/templates/{$slug}-{$name}.php";
  489. // If template file doesn't exist, look in yourtheme/slug.php and yourtheme/woocommerce/slug.php
  490. if ( !$template )
  491. $template = locate_template( array ( "{$slug}.php", "{$woocommerce->template_url}{$slug}.php" ) );
  492. if ( $template )
  493. load_template( $template, false );
  494. }
  495. /**
  496. * Get other templates (e.g. product attributes) passing attributes and including the file.
  497. *
  498. * @access public
  499. * @param mixed $template_name
  500. * @param array $args (default: array())
  501. * @param string $template_path (default: '')
  502. * @param string $default_path (default: '')
  503. * @return void
  504. */
  505. function woocommerce_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
  506. global $woocommerce;
  507. if ( $args && is_array($args) )
  508. extract( $args );
  509. $located = woocommerce_locate_template( $template_name, $template_path, $default_path );
  510. do_action( 'woocommerce_before_template_part', $template_name, $template_path, $located );
  511. include( $located );
  512. do_action( 'woocommerce_after_template_part', $template_name, $template_path, $located );
  513. }
  514. /**
  515. * Locate a template and return the path for inclusion.
  516. *
  517. * This is the load order:
  518. *
  519. * yourtheme / $template_path / $template_name
  520. * yourtheme / $template_name
  521. * $default_path / $template_name
  522. *
  523. * @access public
  524. * @param mixed $template_name
  525. * @param string $template_path (default: '')
  526. * @param string $default_path (default: '')
  527. * @return string
  528. */
  529. function woocommerce_locate_template( $template_name, $template_path = '', $default_path = '' ) {
  530. global $woocommerce;
  531. if ( ! $template_path ) $template_path = $woocommerce->template_url;
  532. if ( ! $default_path ) $default_path = $woocommerce->plugin_path() . '/templates/';
  533. // Look within passed path within the theme - this is priority
  534. $template = locate_template(
  535. array(
  536. trailingslashit( $template_path ) . $template_name,
  537. $template_name
  538. )
  539. );
  540. // Get default template
  541. if ( ! $template )
  542. $template = $default_path . $template_name;
  543. // Return what we found
  544. return apply_filters('woocommerce_locate_template', $template, $template_name, $template_path);
  545. }
  546. /**
  547. * Get Base Currency Code.
  548. *
  549. * @access public
  550. * @return string
  551. */
  552. function get_woocommerce_currency() {
  553. return apply_filters( 'woocommerce_currency', get_option('woocommerce_currency') );
  554. }
  555. /**
  556. * Get full list of currency codes.
  557. *
  558. * @access public
  559. * @return void
  560. */
  561. function get_woocommerce_currencies() {
  562. return array_unique(
  563. apply_filters( 'woocommerce_currencies',
  564. array(
  565. 'AUD' => __( 'Australian Dollars', 'woocommerce' ),
  566. 'BRL' => __( 'Brazilian Real', 'woocommerce' ),
  567. 'CAD' => __( 'Canadian Dollars', 'woocommerce' ),
  568. 'RMB' => __( 'Chinese Yuan', 'woocommerce' ),
  569. 'CZK' => __( 'Czech Koruna', 'woocommerce' ),
  570. 'DKK' => __( 'Danish Krone', 'woocommerce' ),
  571. 'EUR' => __( 'Euros', 'woocommerce' ),
  572. 'HKD' => __( 'Hong Kong Dollar', 'woocommerce' ),
  573. 'HUF' => __( 'Hungarian Forint', 'woocommerce' ),
  574. 'IDR' => __( 'Indonesia Rupiah', 'woocommerce' ),
  575. 'INR' => __( 'Indian Rupee', 'woocommerce' ),
  576. 'ILS' => __( 'Israeli Shekel', 'woocommerce' ),
  577. 'JPY' => __( 'Japanese Yen', 'woocommerce' ),
  578. 'KRW' => __( 'South Korean Won', 'woocommerce' ),
  579. 'MYR' => __( 'Malaysian Ringgits', 'woocommerce' ),
  580. 'MXN' => __( 'Mexican Peso', 'woocommerce' ),
  581. 'NOK' => __( 'Norwegian Krone', 'woocommerce' ),
  582. 'NZD' => __( 'New Zealand Dollar', 'woocommerce' ),
  583. 'PHP' => __( 'Philippine Pesos', 'woocommerce' ),
  584. 'PLN' => __( 'Polish Zloty', 'woocommerce' ),
  585. 'GBP' => __( 'Pounds Sterling', 'woocommerce' ),
  586. 'RON' => __( 'Romanian Leu', 'woocommerce' ),
  587. 'SGD' => __( 'Singapore Dollar', 'woocommerce' ),
  588. 'ZAR' => __( 'South African rand', 'woocommerce' ),
  589. 'SEK' => __( 'Swedish Krona', 'woocommerce' ),
  590. 'CHF' => __( 'Swiss Franc', 'woocommerce' ),
  591. 'TWD' => __( 'Taiwan New Dollars', 'woocommerce' ),
  592. 'THB' => __( 'Thai Baht', 'woocommerce' ),
  593. 'TRY' => __( 'Turkish Lira', 'woocommerce' ),
  594. 'USD' => __( 'US Dollars', 'woocommerce' ),
  595. )
  596. )
  597. );
  598. }
  599. /**
  600. * Get Currency symbol.
  601. *
  602. * @access public
  603. * @param string $currency (default: '')
  604. * @return string
  605. */
  606. function get_woocommerce_currency_symbol( $currency = '' ) {
  607. if ( ! $currency )
  608. $currency = get_woocommerce_currency();
  609. switch ( $currency ) {
  610. case 'BRL' :
  611. $currency_symbol = '&#82;&#36;';
  612. break;
  613. case 'AUD' :
  614. case 'CAD' :
  615. case 'MXN' :
  616. case 'NZD' :
  617. case 'HKD' :
  618. case 'SGD' :
  619. case 'USD' :
  620. $currency_symbol = '&#36;';
  621. break;
  622. case 'EUR' :
  623. $currency_symbol = '&euro;';
  624. break;
  625. case 'CNY' :
  626. case 'RMB' :
  627. case 'JPY' :
  628. $currency_symbol = '&yen;';
  629. break;
  630. case 'KRW' : $currency_symbol = '&#8361;'; break;
  631. case 'TRY' : $currency_symbol = '&#84;&#76;'; break;
  632. case 'NOK' : $currency_symbol = '&#107;&#114;'; break;
  633. case 'ZAR' : $currency_symbol = '&#82;'; break;
  634. case 'CZK' : $currency_symbol = '&#75;&#269;'; break;
  635. case 'MYR' : $currency_symbol = '&#82;&#77;'; break;
  636. case 'DKK' : $currency_symbol = '&#107;&#114;'; break;
  637. case 'HUF' : $currency_symbol = '&#70;&#116;'; break;
  638. case 'IDR' : $currency_symbol = 'Rp'; break;
  639. case 'INR' : $currency_symbol = '&#8377;'; break;
  640. case 'ILS' : $currency_symbol = '&#8362;'; break;
  641. case 'PHP' : $currency_symbol = '&#8369;'; break;
  642. case 'PLN' : $currency_symbol = '&#122;&#322;'; break;
  643. case 'SEK' : $currency_symbol = '&#107;&#114;'; break;
  644. case 'CHF' : $currency_symbol = '&#67;&#72;&#70;'; break;
  645. case 'TWD' : $currency_symbol = '&#78;&#84;&#36;'; break;
  646. case 'THB' : $currency_symbol = '&#3647;'; break;
  647. case 'GBP' : $currency_symbol = '&pound;'; break;
  648. case 'RON' : $currency_symbol = 'lei'; break;
  649. default : $currency_symbol = ''; break;
  650. }
  651. return apply_filters( 'woocommerce_currency_symbol', $currency_symbol, $currency );
  652. }
  653. /**
  654. * Format the price with a currency symbol.
  655. *
  656. * @access public
  657. * @param float $price
  658. * @param array $args (default: array())
  659. * @return string
  660. */
  661. function woocommerce_price( $price, $args = array() ) {
  662. global $woocommerce;
  663. extract( shortcode_atts( array(
  664. 'ex_tax_label' => '0'
  665. ), $args ) );
  666. $return = '';
  667. $num_decimals = (int) get_option( 'woocommerce_price_num_decimals' );
  668. $currency_pos = get_option( 'woocommerce_currency_pos' );
  669. $currency_symbol = get_woocommerce_currency_symbol();
  670. $decimal_sep = wp_specialchars_decode( stripslashes( get_option( 'woocommerce_price_decimal_sep' ) ), ENT_QUOTES );
  671. $thousands_sep = wp_specialchars_decode( stripslashes( get_option( 'woocommerce_price_thousand_sep' ) ), ENT_QUOTES );
  672. $price = apply_filters( 'raw_woocommerce_price', (double) $price );
  673. $price = number_format( $price, $num_decimals, $decimal_sep, $thousands_sep );
  674. if ( get_option( 'woocommerce_price_trim_zeros' ) == 'yes' && $num_decimals > 0 )
  675. $price = woocommerce_trim_zeros( $price );
  676. $return = '<span class="amount">' . sprintf( get_woocommerce_price_format(), $currency_symbol, $price ) . '</span>';
  677. if ( $ex_tax_label && get_option( 'woocommerce_calc_taxes' ) == 'yes' )
  678. $return .= ' <small>' . $woocommerce->countries->ex_tax_or_vat() . '</small>';
  679. return $return;
  680. }
  681. function get_woocommerce_price_format() {
  682. $currency_pos = get_option( 'woocommerce_currency_pos' );
  683. switch ( $currency_pos ) {
  684. case 'left' :
  685. $format = '%1$s%2$s';
  686. break;
  687. case 'right' :
  688. $format = '%2$s%1$s';
  689. break;
  690. case 'left_space' :
  691. $format = '%1$s&nbsp;%2$s';
  692. break;
  693. case 'right_space' :
  694. $format = '%2$s&nbsp;%1$s';
  695. break;
  696. }
  697. return apply_filters( 'woocommerce_price_format', $format, $currency_pos );
  698. }
  699. /**
  700. * Trim trailing zeros off prices.
  701. *
  702. * @access public
  703. * @param mixed $price
  704. * @return string
  705. */
  706. function woocommerce_trim_zeros( $price ) {
  707. return preg_replace( '/' . preg_quote( get_option( 'woocommerce_price_decimal_sep' ), '/' ) . '0++$/', '', $price );
  708. }
  709. /**
  710. * Formal decimal numbers - format to 4 dp and remove trailing zeros.
  711. *
  712. * @access public
  713. * @param mixed $number
  714. * @return string
  715. */
  716. function woocommerce_format_decimal( $number, $dp = '' ) {
  717. if ( $dp == '' )
  718. $dp = intval( get_option( 'woocommerce_price_num_decimals' ) );
  719. $number = number_format( (float) $number, (int) $dp, '.', '' );
  720. if ( strstr( $number, '.' ) )
  721. $number = rtrim( rtrim( $number, '0' ), '.' );
  722. return $number;
  723. }
  724. /**
  725. * Formal total costs - format to the number of decimal places for the base currency.
  726. *
  727. * @access public
  728. * @param mixed $number
  729. * @return float
  730. */
  731. function woocommerce_format_total( $number ) {
  732. return number_format( (float) $number, (int) get_option( 'woocommerce_price_num_decimals' ), '.', '' );
  733. }
  734. /**
  735. * Clean variables
  736. *
  737. * @access public
  738. * @param string $var
  739. * @return string
  740. */
  741. function woocommerce_clean( $var ) {
  742. return sanitize_text_field( $var );
  743. }
  744. /**
  745. * Merge two arrays
  746. *
  747. * @access public
  748. * @param array $a1
  749. * @param array $a2
  750. * @return array
  751. */
  752. function woocommerce_array_overlay( $a1, $a2 ) {
  753. foreach( $a1 as $k => $v ) {
  754. if ( ! array_key_exists( $k, $a2 ) )
  755. continue;
  756. if ( is_array( $v ) && is_array( $a2[ $k ] ) ) {
  757. $a1[ $k ] = woocommerce_array_overlay( $v, $a2[ $k ] );
  758. } else {
  759. $a1[ $k ] = $a2[ $k ];
  760. }
  761. }
  762. return $a1;
  763. }
  764. /**
  765. * Get top term
  766. * http://wordpress.stackexchange.com/questions/24794/get-the-the-top-level-parent-of-a-custom-taxonomy-term
  767. *
  768. * @access public
  769. * @param int $term_id
  770. * @param string $taxonomy
  771. * @return int
  772. */
  773. function woocommerce_get_term_top_most_parent( $term_id, $taxonomy ) {
  774. // start from the current term
  775. $parent = get_term_by( 'id', $term_id, $taxonomy );
  776. // climb up the hierarchy until we reach a term with parent = '0'
  777. while ( $parent->parent != '0' ) {
  778. $term_id = $parent->parent;
  779. $parent = get_term_by( 'id', $term_id, $taxonomy);
  780. }
  781. return $parent;
  782. }
  783. /**
  784. * Variation Formatting
  785. *
  786. * Gets a formatted version of variation data or item meta
  787. *
  788. * @access public
  789. * @param string $variation (default: '')
  790. * @param bool $flat (default: false)
  791. * @return string
  792. */
  793. function woocommerce_get_formatted_variation( $variation = '', $flat = false ) {
  794. global $woocommerce;
  795. if ( is_array( $variation ) ) {
  796. if ( ! $flat )
  797. $return = '<dl class="variation">';
  798. else
  799. $return = '';
  800. $variation_list = array();
  801. foreach ( $variation as $name => $value ) {
  802. if ( ! $value )
  803. continue;
  804. // If this is a term slug, get the term's nice name
  805. if ( taxonomy_exists( esc_attr( str_replace( 'attribute_', '', $name ) ) ) ) {
  806. $term = get_term_by( 'slug', $value, esc_attr( str_replace( 'attribute_', '', $name ) ) );
  807. if ( ! is_wp_error( $term ) && $term->name )
  808. $value = $term->name;
  809. }
  810. if ( $flat )
  811. $variation_list[] = $woocommerce->attribute_label(str_replace('attribute_', '', $name)).': '.$value;
  812. else
  813. $variation_list[] = '<dt>'.$woocommerce->attribute_label(str_replace('attribute_', '', $name)).':</dt><dd>'.$value.'</dd>';
  814. }
  815. if ( $flat )
  816. $return .= implode( ', ', $variation_list );
  817. else
  818. $return .= implode( '', $variation_list );
  819. if ( ! $flat )
  820. $return .= '</dl>';
  821. return $return;
  822. }
  823. }
  824. if ( ! function_exists( 'woocommerce_rgb_from_hex' ) ) {
  825. /**
  826. * Hex darker/lighter/contrast functions for colours
  827. *
  828. * @access public
  829. * @param mixed $color
  830. * @return string
  831. */
  832. function woocommerce_rgb_from_hex( $color ) {
  833. $color = str_replace( '#', '', $color );
  834. // Convert shorthand colors to full format, e.g. "FFF" -> "FFFFFF"
  835. $color = preg_replace( '~^(.)(.)(.)$~', '$1$1$2$2$3$3', $color );
  836. $rgb['R'] = hexdec( $color{0}.$color{1} );
  837. $rgb['G'] = hexdec( $color{2}.$color{3} );
  838. $rgb['B'] = hexdec( $color{4}.$color{5} );
  839. return $rgb;
  840. }
  841. }
  842. if ( ! function_exists( 'woocommerce_hex_darker' ) ) {
  843. /**
  844. * Hex darker/lighter/contrast functions for colours
  845. *
  846. * @access public
  847. * @param mixed $color
  848. * @param int $factor (default: 30)
  849. * @return string
  850. */
  851. function woocommerce_hex_darker( $color, $factor = 30 ) {
  852. $base = woocommerce_rgb_from_hex( $color );
  853. $color = '#';
  854. foreach ($base as $k => $v) :
  855. $amount = $v / 100;
  856. $amount = round($amount * $factor);
  857. $new_decimal = $v - $amount;
  858. $new_hex_component = dechex($new_decimal);
  859. if(strlen($new_hex_component) < 2) :
  860. $new_hex_component = "0".$new_hex_component;
  861. endif;
  862. $color .= $new_hex_component;
  863. endforeach;
  864. return $color;
  865. }
  866. }
  867. if ( ! function_exists( 'woocommerce_hex_lighter' ) ) {
  868. /**
  869. * Hex darker/lighter/contrast functions for colours
  870. *
  871. * @access public
  872. * @param mixed $color
  873. * @param int $factor (default: 30)
  874. * @return string
  875. */
  876. function woocommerce_hex_lighter( $color, $factor = 30 ) {
  877. $base = woocommerce_rgb_from_hex( $color );
  878. $color = '#';
  879. foreach ($base as $k => $v) :
  880. $amount = 255 - $v;
  881. $amount = $amount / 100;
  882. $amount = round($amount * $factor);
  883. $new_decimal = $v + $amount;
  884. $new_hex_component = dechex($new_decimal);
  885. if(strlen($new_hex_component) < 2) :
  886. $new_hex_component = "0".$new_hex_component;
  887. endif;
  888. $color .= $new_hex_component;
  889. endforeach;
  890. return $color;
  891. }
  892. }
  893. if ( ! function_exists( 'woocommerce_light_or_dark' ) ) {
  894. /**
  895. * Detect if we should use a light or dark colour on a background colour
  896. *
  897. * @access public
  898. * @param mixed $color
  899. * @param string $dark (default: '#000000')
  900. * @param string $light (default: '#FFFFFF')
  901. * @return string
  902. */
  903. function woocommerce_light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) {
  904. //return ( hexdec( $color ) > 0xffffff / 2 ) ? $dark : $light;
  905. $hex = str_replace( '#', '', $color );
  906. $c_r = hexdec( substr( $hex, 0, 2 ) );
  907. $c_g = hexdec( substr( $hex, 2, 2 ) );
  908. $c_b = hexdec( substr( $hex, 4, 2 ) );
  909. $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
  910. return $brightness > 155 ? $dark : $light;
  911. }
  912. }
  913. if ( ! function_exists( 'woocommerce_format_hex' ) ) {
  914. /**
  915. * Format string as hex
  916. *
  917. * @access public
  918. * @param string $hex
  919. * @return string
  920. */
  921. function woocommerce_format_hex( $hex ) {
  922. $hex = trim( str_replace( '#', '', $hex ) );
  923. if ( strlen( $hex ) == 3 ) {
  924. $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
  925. }
  926. if ( $hex ) return '#' . $hex;
  927. }
  928. }
  929. /**
  930. * Exclude order comments from queries and RSS
  931. *
  932. * This code should exclude shop_order comments from queries. Some queries (like the recent comments widget on the dashboard) are hardcoded
  933. * and are not filtered, however, the code current_user_can( 'read_post', $comment->comment_post_ID ) should keep them safe since only admin and
  934. * shop managers can view orders anyway.
  935. *
  936. * The frontend view order pages get around this filter by using remove_filter('comments_clauses', 'woocommerce_exclude_order_comments');
  937. *
  938. * @access public
  939. * @param array $clauses
  940. * @return array
  941. */
  942. function woocommerce_exclude_order_comments( $clauses ) {
  943. global $wpdb, $typenow, $pagenow;
  944. if ( is_admin() && ( $typenow == 'shop_order' || $pagenow == 'edit-comments.php' ) && current_user_can( 'manage_woocommerce' ) )
  945. return $clauses; // Don't hide when viewing orders in admin
  946. if ( ! $clauses['join'] )
  947. $clauses['join'] = '';
  948. if ( ! strstr( $clauses['join'], "JOIN $wpdb->posts" ) )
  949. $clauses['join'] .= " LEFT JOIN $wpdb->posts ON $wpdb->comments.comment_post_ID = $wpdb->posts.ID ";
  950. if ( $clauses['where'] )
  951. $clauses['where'] .= ' AND ';
  952. $clauses['where'] .= " $wpdb->posts.post_type NOT IN ('shop_order') ";
  953. return $clauses;
  954. }
  955. add_filter( 'comments_clauses', 'woocommerce_exclude_order_comments', 10, 1);
  956. /**
  957. * Exclude order comments from queries and RSS
  958. *
  959. * @access public
  960. * @param string $join
  961. * @return string
  962. */
  963. function woocommerce_exclude_order_comments_from_feed_join( $join ) {
  964. global $wpdb;
  965. if ( ! $join )
  966. $join = " LEFT JOIN $wpdb->posts ON $wpdb->comments.comment_post_ID = $wpdb->posts.ID ";
  967. return $join;
  968. }
  969. add_action( 'comment_feed_join', 'woocommerce_exclude_order_comments_from_feed_join' );
  970. /**
  971. * Exclude order comments from queries and RSS
  972. *
  973. * @access public
  974. * @param string $where
  975. * @return string
  976. */
  977. function woocommerce_exclude_order_comments_from_feed_where( $where ) {
  978. global $wpdb;
  979. if ( $where )
  980. $where .= ' AND ';
  981. $where .= " $wpdb->posts.post_type NOT IN ('shop_order') ";
  982. return $where;
  983. }
  984. add_action( 'comment_feed_where', 'woocommerce_exclude_order_comments_from_feed_where' );
  985. /**
  986. * Order Status completed - GIVE DOWNLOADABLE PRODUCT ACCESS TO CUSTOMER
  987. *
  988. * @access public
  989. * @param int $order_id
  990. * @return void
  991. */
  992. function woocommerce_downloadable_product_permissions( $order_id ) {
  993. global $wpdb;
  994. if (get_post_meta( $order_id, __( 'Download Permissions Granted', 'woocommerce' ), true)==1) return; // Only do this once
  995. $order = new WC_Order( $order_id );
  996. if (sizeof($order->get_items())>0) foreach ($order->get_items() as $item) :
  997. if ($item['product_id']>0) :
  998. $_product = $order->get_product_from_item( $item );
  999. if ( $_product->exists() && $_product->is_downloadable() ) :
  1000. $product_id = ($item['variation_id']>0) ? $item['variation_id'] : $item['product_id'];
  1001. $file_download_paths = apply_filters( 'woocommerce_file_download_paths', get_post_meta( $product_id, '_file_paths', true ), $product_id, $order_id, $item );
  1002. if ( ! empty( $file_download_paths ) ) {
  1003. foreach ( $file_download_paths as $download_id => $file_path ) {
  1004. woocommerce_downloadable_file_permission( $download_id, $product_id, $order );
  1005. }
  1006. }
  1007. endif;
  1008. endif;
  1009. endforeach;
  1010. update_post_meta( $order_id, __( 'Download Permissions Granted', 'woocommerce' ), 1);
  1011. }
  1012. add_action('woocommerce_order_status_completed', 'woocommerce_downloadable_product_permissions');
  1013. /**
  1014. * Grant downloadable product access to the file identified by $download_id
  1015. *
  1016. * @access public
  1017. * @param string $download_id file identifier
  1018. * @param int $product_id product identifier
  1019. * @param WC_Order $order the order
  1020. */
  1021. function woocommerce_downloadable_file_permission( $download_id, $product_id, $order ) {
  1022. global $wpdb;
  1023. $user_email = $order->billing_email;
  1024. $limit = trim( get_post_meta( $product_id, '_download_limit', true ) );
  1025. $expiry = trim( get_post_meta( $product_id, '_download_expiry', true ) );
  1026. $limit = empty( $limit ) ? '' : (int) $limit;
  1027. // Default value is NULL in the table schema
  1028. $expiry = empty( $expiry ) ? null : (int) $expiry;
  1029. if ( $expiry ) $expiry = date_i18n( "Y-m-d", strtotime( 'NOW + ' . $expiry . ' DAY' ) );
  1030. $data = array(
  1031. 'download_id' => $download_id,
  1032. 'product_id' => $product_id,
  1033. 'user_id' => $order->user_id,
  1034. 'user_email' => $user_email,
  1035. 'order_id' => $order->id,
  1036. 'order_key' => $order->order_key,
  1037. 'downloads_remaining' => $limit,
  1038. 'access_granted' => current_time( 'mysql' ),
  1039. 'download_count' => 0
  1040. );
  1041. $format = array(
  1042. '%s',
  1043. '%s',
  1044. '%s',
  1045. '%s',
  1046. '%s',
  1047. '%s',
  1048. '%s',
  1049. '%s',
  1050. '%d'
  1051. );
  1052. if ( ! is_null( $expiry ) ) {
  1053. $data['access_expires'] = $expiry;
  1054. $format[] = '%s';
  1055. }
  1056. // Downloadable product - give access to the customer
  1057. $wpdb->insert( $wpdb->prefix . 'woocommerce_downloadable_product_permissions',
  1058. $data,
  1059. $format
  1060. );
  1061. }
  1062. if ( get_option('woocommerce_downloads_grant_access_after_payment') == 'yes' )
  1063. add_action( 'woocommerce_order_status_processing', 'woocommerce_downloadable_product_permissions' );
  1064. /**
  1065. * Order Status completed - This is a paying customer
  1066. *
  1067. * @access public
  1068. * @param int $order_id
  1069. * @return void
  1070. */
  1071. function woocommerce_paying_customer( $order_id ) {
  1072. $order = new WC_Order( $order_id );
  1073. if ( $order->user_id > 0 ) {
  1074. update_user_meta( $order->user_id, 'paying_customer', 1 );
  1075. $old_count = absint( get_user_meta( $order->user_id, '_order_count', true ) );
  1076. update_user_meta( $order->user_id, '_order_count', $old_count + 1 );
  1077. }
  1078. }
  1079. add_action( 'woocommerce_order_status_completed', 'woocommerce_paying_customer' );
  1080. /**
  1081. * Filter to allow product_cat in the permalinks for products.
  1082. *
  1083. * @access public
  1084. * @param string $permalink The existing permalink URL.
  1085. * @param object $post
  1086. * @return string
  1087. */
  1088. function woocommerce_product_post_type_link( $permalink, $post ) {
  1089. // Abort if post is not a product
  1090. if ( $post->post_type !== 'product' )
  1091. return $permalink;
  1092. // Abort early if the placeholder rewrite tag isn't in the generated URL
  1093. if ( false === strpos( $permalink, '%' ) )
  1094. return $permalink;
  1095. // Get the custom taxonomy terms in use by this post
  1096. $terms = get_the_terms( $post->ID, 'product_cat' );
  1097. if ( empty( $terms ) ) {
  1098. // If no terms are assigned to this post, use a string instead (can't leave the placeholder there)
  1099. $product_cat = _x( 'uncategorized', 'slug', 'woocommerce' );
  1100. } else {
  1101. // Replace the placeholder rewrite tag with the first term's slug
  1102. $first_term = array_shift( $terms );
  1103. $product_cat = $first_term->slug;
  1104. }
  1105. $find = array(
  1106. '%year%',
  1107. '%monthnum%',
  1108. '%day%',
  1109. '%hour%',
  1110. '%minute%',
  1111. '%second%',
  1112. '%post_id%',
  1113. '%category%',
  1114. '%product_cat%'
  1115. );
  1116. $replace = array(
  1117. date_i18n( 'Y', strtotime( $post->post_date ) ),
  1118. date_i18n( 'm', strtotime( $post->post_date ) ),
  1119. date_i18n( 'd', strtotime( $post->post_date ) ),
  1120. date_i18n( 'H', strtotime( $post->post_date ) ),
  1121. date_i18n( 'i', strtotime( $post->post_date ) ),
  1122. date_i18n( 's', strtotime( $post->post_date ) ),
  1123. $post->ID,
  1124. $product_cat,
  1125. $product_cat
  1126. );
  1127. $replace = array_map( 'sanitize_title', $replace );
  1128. $permalink = str_replace( $find, $replace, $permalink );
  1129. return $permalink;
  1130. }
  1131. add_filter( 'post_type_link', 'woocommerce_product_post_type_link', 10, 2 );
  1132. /**
  1133. * Add term ordering to get_terms
  1134. *
  1135. * It enables the support a 'menu_order' parameter to get_terms for the product_cat taxonomy.
  1136. * By default it is 'ASC'. It accepts 'DESC' too
  1137. *
  1138. * To disable it, set it ot false (or 0)
  1139. *
  1140. * @access public
  1141. * @param array $clauses
  1142. * @param array $taxonomies
  1143. * @param array $args
  1144. * @return array
  1145. */
  1146. function woocommerce_terms_clauses( $clauses, $taxonomies, $args ) {
  1147. global $wpdb, $woocommerce;
  1148. // No sorting when menu_order is false
  1149. if ( isset($args['menu_order']) && $args['menu_order'] == false ) return $clauses;
  1150. // No sorting when orderby is non default
  1151. if ( isset($args['orderby']) && $args['orderby'] != 'name' ) return $clauses;
  1152. // No sorting in admin when sorting by a column
  1153. if ( is_admin() && isset($_GET['orderby']) ) return $clauses;
  1154. // wordpress should give us the taxonomies asked when calling the get_terms function. Only apply to categories and pa_ attributes
  1155. $found = false;
  1156. foreach ( (array) $taxonomies as $taxonomy ) :
  1157. if ( strstr($taxonomy, 'pa_') || in_array( $taxonomy, apply_filters( 'woocommerce_sortable_taxonomies', array( 'product_cat' ) ) ) ) :
  1158. $found = true;
  1159. break;
  1160. endif;
  1161. endforeach;
  1162. if (!$found) return $clauses;
  1163. // Meta name
  1164. if ( ! empty( $taxonomies[0] ) && strstr($taxonomies[0], 'pa_') ) {
  1165. $meta_name = 'order_' . esc_attr($taxonomies[0]);
  1166. } else {
  1167. $meta_name = 'order';
  1168. }
  1169. // query fields
  1170. if ( strpos('COUNT(*)', $clauses['fields']) === false ) $clauses['fields'] .= ', tm.* ';
  1171. //query join
  1172. $clauses['join'] .= " LEFT JOIN {$wpdb->woocommerce_termmeta} AS tm ON (t.term_id = tm.woocommerce_term_id AND tm.meta_key = '". $meta_name ."') ";
  1173. // default to ASC
  1174. if ( ! isset($args['menu_order']) || ! in_array( strtoupper($args['menu_order']), array('ASC', 'DESC')) ) $args['menu_order'] = 'ASC';
  1175. $order = "ORDER BY CAST(tm.meta_value AS SIGNED) " . $args['menu_order'];
  1176. if ( $clauses['orderby'] ):
  1177. $clauses['orderby'] = str_replace('ORDER BY', $order . ',', $clauses['orderby'] );
  1178. else:
  1179. $clauses['orderby'] = $order;
  1180. endif;
  1181. return $clauses;
  1182. }
  1183. add_filter( 'terms_clauses', 'woocommerce_terms_clauses', 10, 3);
  1184. /**
  1185. * woocommerce_get_product_terms function.
  1186. *
  1187. * Gets product terms in the order they are defined in the backend.
  1188. *
  1189. * @access public
  1190. * @param mixed $object_id
  1191. * @param mixed $taxonomy
  1192. * @param mixed $fields ids, names, slugs, all
  1193. * @return array
  1194. */
  1195. function woocommerce_get_product_terms( $object_id, $taxonomy, $fields = 'all' ) {
  1196. if ( ! taxonomy_exists( $taxonomy ) )
  1197. return array();
  1198. $terms = array();
  1199. $object_terms = get_the_terms( $object_id, $taxonomy );
  1200. $all_terms = array_flip( get_terms( $taxonomy, array( 'menu_order' => 'ASC', 'fields' => 'ids' ) ) );
  1201. switch ( $fields ) {
  1202. case 'names' :
  1203. foreach ( $object_terms as $term )
  1204. $terms[ $all_terms[ $term->term_id ] ] = $term->name;
  1205. break;
  1206. case 'ids' :
  1207. foreach ( $object_terms as $term )
  1208. $terms[ $all_terms[ $term->term_id ] ] = $term->term_id;
  1209. break;
  1210. case 'slugs' :
  1211. foreach ( $object_terms as $term )
  1212. $terms[ $all_terms[ $term->term_id ] ] = $term->slug;
  1213. break;
  1214. case 'all' :
  1215. foreach ( $object_terms as $term )
  1216. $terms[ $all_terms[ $term->term_id ] ] = $term;
  1217. break;
  1218. }
  1219. ksort( $terms );
  1220. return $terms;
  1221. }
  1222. /**
  1223. * WooCommerce Dropdown categories
  1224. *
  1225. * Stuck with this until a fix for http://core.trac.wordpress.org/ticket/13258
  1226. * We use a custom walker, just like WordPress does
  1227. *
  1228. * @access public
  1229. * @param int $show_counts (default: 1)
  1230. * @param int $hierarchical (default: 1)
  1231. * @param int $show_uncategorized (default: 1)
  1232. * @return string
  1233. */
  1234. function woocommerce_product_dropdown_categories( $show_counts = 1, $hierarchical = 1, $show_uncategorized = 1, $orderby = '' ) {
  1235. global $wp_query, $woocommerce;
  1236. include_once( $woocommerce->plugin_path() . '/classes/walkers/class-product-cat-dropdown-walker.php' );
  1237. $r = array();
  1238. $r['pad_counts'] = 1;
  1239. $r['hierarchical'] = $hierarchical;
  1240. $r['hide_empty'] = 1;
  1241. $r['show_count'] = $show_counts;
  1242. $r['selected'] = ( isset( $wp_query->query['product_cat'] ) ) ? $wp_query->query['product_cat'] : '';
  1243. $r['menu_order'] = false;
  1244. if ( $orderby == 'order' )
  1245. $r['menu_order'] = 'asc';
  1246. elseif ( $orderby )
  1247. $r['orderby'] = $orderby;
  1248. $terms = get_terms( 'product_cat', $r );
  1249. if (!$terms) return;
  1250. $output = "<select name='product_cat' id='dropdown_product_cat'>";
  1251. $output .= '<option value="" ' . selected( isset( $_GET['product_cat'] ) ? $_GET['product_cat'] : '', '', false ) . '>'.__( 'Select a category', 'woocommerce' ).'</option>';
  1252. $output .= woocommerce_walk_category_dropdown_tree( $terms, 0, $r );
  1253. if ( $show_uncategorized )
  1254. $output .= '<option value="0" ' . selected( isset( $_GET['product_cat'] ) ? $_GET['product_cat'] : '', '0', false ) . '>' . __( 'Uncategorized', 'woocommerce' ) . '</option>';
  1255. $output .="</select>";
  1256. echo $output;
  1257. }
  1258. /**
  1259. * Walk the Product Categories.
  1260. *
  1261. * @access public
  1262. * @return void
  1263. */
  1264. function woocommerce_walk_category_dropdown_tree() {
  1265. $args = func_get_args();
  1266. // the user's options are the third parameter
  1267. if ( empty($args[2]['walker']) || !is_a($args[2]['walker'], 'Walker') )
  1268. $walker = new WC_Product_Cat_Dropdown_Walker;
  1269. else
  1270. $walker = $args[2]['walker'];
  1271. return call_user_func_array(array( &$walker, 'walk' ), $args );
  1272. }
  1273. /**
  1274. * WooCommerce Term/Order item Meta API - set table name
  1275. *
  1276. * @access public
  1277. * @return void
  1278. */
  1279. function woocommerce_taxonomy_metadata_wpdbfix() {
  1280. global $wpdb;
  1281. $termmeta_name = 'woocommerce_termmeta';
  1282. $itemmeta_name = 'woocommerce_order_itemmeta';
  1283. $wpdb->woocommerce_termmeta = $wpdb->prefix . $termmeta_name;
  1284. $wpdb->order_itemmeta = $wpdb->prefix . $itemmeta_name;
  1285. $wpdb->tables[] = 'woocommerce_termmeta';
  1286. $wpdb->tables[] = 'order_itemmeta';
  1287. }
  1288. add_action( 'init', 'woocommerce_taxonomy_metadata_wpdbfix', 0 );
  1289. add_action( 'switch_blog', 'woocommerce_taxonomy_metadata_wpdbfix', 0 );
  1290. /**
  1291. * WooCommerce Term Meta API - Update term meta
  1292. *
  1293. * @access public
  1294. * @param mixed $term_id
  1295. * @param mixed $meta_key
  1296. * @param mixed $meta_value
  1297. * @param string $prev_value (default: '')
  1298. * @return bool
  1299. */
  1300. function update_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {
  1301. return update_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $prev_value );
  1302. }
  1303. /**
  1304. * WooCommerce Term Meta API - Add term meta
  1305. *
  1306. * @access public
  1307. * @param mixed $term_id
  1308. * @param mixed $meta_key
  1309. * @param mixed $meta_value
  1310. * @param bool $unique (default: false)
  1311. * @return bool
  1312. */
  1313. function add_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $unique = false ){
  1314. return add_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $unique );
  1315. }
  1316. /**
  1317. * WooCommerce Term Meta API - Delete term meta
  1318. *
  1319. * @access public
  1320. * @param mixed $term_id
  1321. * @param mixed $meta_key
  1322. * @param string $meta_value (default: '')
  1323. * @param bool $delete_all (default: false)
  1324. * @return bool
  1325. */
  1326. function delete_woocommerce_term_meta( $term_id, $meta_key, $meta_value = '', $delete_all = false ) {
  1327. return delete_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $delete_all );
  1328. }
  1329. /**
  1330. * WooCommerce Term Meta API - Get term meta
  1331. *
  1332. * @access public
  1333. * @param mixed $term_id
  1334. * @param mixed $key
  1335. * @param bool $single (default: true)
  1336. * @return mixed
  1337. */
  1338. function get_woocommerce_term_meta( $term_id, $key, $single = true ) {
  1339. return get_metadata( 'woocommerce_term', $term_id, $key, $single );
  1340. }
  1341. /**
  1342. * Move a term before the a given element of its hierarchy level
  1343. *
  1344. * @access public
  1345. * @param int $the_term
  1346. * @param int $next_id the id of the next sibling element in save hierarchy level
  1347. * @param string $taxonomy
  1348. * @param int $index (default: 0)
  1349. * @param mixed $terms (default: null)
  1350. * @return int
  1351. */
  1352. function woocommerce_order_terms( $the_term, $next_id, $taxonomy, $index = 0, $terms = null ) {
  1353. if( ! $terms ) $terms = get_terms($taxonomy, 'menu_order=ASC&hide_empty=0&parent=0' );
  1354. if( empty( $terms ) ) return $index;
  1355. $id = $the_term->term_id;
  1356. $term_in_level = false; // flag: is our term to order in this level of terms
  1357. foreach ($terms as $term) {
  1358. if( $term->term_id == $id ) { // our term to order, we skip
  1359. $term_in_level = true;
  1360. continue; // our term to order, we skip
  1361. }
  1362. // the nextid of our term to order, lets move our term here
  1363. if(null !== $next_id && $term->term_id == $next_id) {
  1364. $index++;
  1365. $index = woocommerce_set_term_order($id, $index, $taxonomy, true);
  1366. }
  1367. // set order
  1368. $index++;
  1369. $index = woocommerce_set_term_order($term->term_id, $index, $taxonomy);
  1370. // if that term has children we walk through them
  1371. $children = get_terms($taxonomy, "parent={$term->term_id}&menu_order=ASC&hide_empty=0");
  1372. if( !empty($children) ) {
  1373. $index = woocommerce_order_terms( $the_term, $next_id, $taxonomy, $index, $children );
  1374. }
  1375. }
  1376. // no nextid meaning our term is in last position
  1377. if( $term_in_level && null === $next_id )
  1378. $index = woocommerce_set_term_order($id, $index+1, $taxonomy, true);
  1379. return $index;
  1380. }
  1381. /**
  1382. * Set the sort order of a term
  1383. *
  1384. * @access public
  1385. * @param int $term_id
  1386. * @param int $index
  1387. * @param string $taxonomy
  1388. * @param bool $recursive (default: false)
  1389. * @return int
  1390. */
  1391. function woocommerce_set_term_order( $term_id, $index, $taxonomy, $recursive = false ) {
  1392. global $wpdb;
  1393. $term_id = (int) $term_id;
  1394. $index = (int) $index;
  1395. // Meta name
  1396. if (strstr($taxonomy, 'pa_')) :
  1397. $meta_name = 'order_' . esc_attr($taxonomy);
  1398. else :
  1399. $meta_name = 'order';
  1400. endif;
  1401. update_woocommerce_term_meta( $term_id, $meta_name, $index );
  1402. if( ! $recursive ) return $index;
  1403. $children = get_terms($taxonomy, "parent=$term_id&menu_order=ASC&hide_empty=0");
  1404. foreach ( $children as $term ) {
  1405. $index ++;
  1406. $index = woocommerce_set_term_order($term->term_id, $index, $taxonomy, true);
  1407. }
  1408. clean_term_cache( $term_id, $taxonomy );
  1409. return $index;
  1410. }
  1411. /**
  1412. * let_to_num function.
  1413. *
  1414. * This function transforms the php.ini notation for numbers (like '2M') to an integer.
  1415. *
  1416. * @access public
  1417. * @param $size
  1418. * @return int
  1419. */
  1420. function woocommerce_let_to_num( $size ) {
  1421. $l = substr( $size, -1 );
  1422. $ret = substr( $size, 0, -1 );
  1423. switch( strtoupper( $l ) ) {
  1424. case 'P':
  1425. $ret *= 1024;
  1426. case 'T':
  1427. $ret *= 1024;
  1428. case 'G':
  1429. $ret *= 1024;
  1430. case 'M':
  1431. $ret *= 1024;
  1432. case 'K':
  1433. $ret *= 1024;
  1434. }
  1435. return $ret;
  1436. }
  1437. /**
  1438. * woocommerce_customer_bought_product
  1439. *
  1440. * Checks if a user (by email) has bought an item
  1441. *
  1442. * @access public
  1443. * @param string $customer_email
  1444. * @param int $user_id
  1445. * @param int $product_id
  1446. * @return bool
  1447. */
  1448. function woocommerce_customer_bought_product( $customer_email, $user_id, $product_id ) {
  1449. global $wpdb;
  1450. $emails = array();
  1451. if ( $user_id ) {
  1452. $user = get_user_by( 'id', $user_id );
  1453. $emails[] = $user->user_email;
  1454. }
  1455. if ( is_email( $customer_email ) )
  1456. $emails[] = $customer_email;
  1457. if ( sizeof( $emails ) == 0 )
  1458. return false;
  1459. return $wpdb->get_var( $wpdb->prepare( "
  1460. SELECT COUNT( order_items.order_item_id )
  1461. FROM {$wpdb->prefix}woocommerce_order_items as order_items
  1462. LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS itemmeta ON order_items.order_item_id = itemmeta.order_item_id
  1463. LEFT JOIN {$wpdb->postmeta} AS postmeta ON order_items.order_id = postmeta.post_id
  1464. LEFT JOIN {$wpdb->term_relationships} AS rel ON postmeta.post_id = rel.object_ID
  1465. LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
  1466. LEFT JOIN {$wpdb->terms} AS term USING( term_id )
  1467. WHERE term.slug IN ('" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "')
  1468. AND tax.taxonomy = 'shop_order_status'
  1469. AND (
  1470. (
  1471. itemmeta.meta_key = '_variation_id'
  1472. AND itemmeta.meta_value = %s
  1473. ) OR (
  1474. itemmeta.meta_key = '_product_id'
  1475. AND itemmeta.meta_value = %s
  1476. )
  1477. )
  1478. AND (
  1479. (
  1480. postmeta.meta_key = '_billing_email'
  1481. AND postmeta.meta_value IN ( '" . implode( "','", array_unique( $emails ) ) . "' )
  1482. ) OR (
  1483. postmeta.meta_key = '_customer_user'
  1484. AND postmeta.meta_value = %s AND postmeta.meta_value > 0
  1485. )
  1486. )
  1487. ", $product_id, $product_id, $user_id ) );
  1488. }
  1489. /**
  1490. * Return the count of processing orders.
  1491. *
  1492. * @access public
  1493. * @return int
  1494. */
  1495. function woocommerce_processing_order_count() {
  1496. if ( false === ( $order_count = get_transient( 'woocommerce_processing_order_count' ) ) ) {
  1497. $order_statuses = get_terms( 'shop_order_status' );
  1498. $order_count = false;
  1499. foreach ( $order_statuses as $status ) {
  1500. if( $status->slug === 'processing' ) {
  1501. $order_count += $status->count;
  1502. break;
  1503. }
  1504. }
  1505. $order_count = apply_filters( 'woocommerce_admin_menu_count', intval( $order_count ) );
  1506. set_transient( 'woocommerce_processing_order_count', $order_count );
  1507. }
  1508. return $order_count;
  1509. }
  1510. /**
  1511. * Get capabilities for WooCommerce - these are assigned to admin/shop manager during installation or reset
  1512. *
  1513. * @access public
  1514. * @return void
  1515. */
  1516. function woocommerce_get_core_capabilities() {
  1517. $capabilities = array();
  1518. $capabilities['core'] = array(
  1519. "manage_woocommerce",
  1520. "view_woocommerce_reports"
  1521. );
  1522. $capability_types = array( 'product', 'shop_order', 'shop_coupon' );
  1523. foreach( $capability_types as $capability_type ) {
  1524. $capabilities[ $capability_type ] = array(
  1525. // Post type
  1526. "edit_{$capability_type}",
  1527. "read_{$capability_type}",
  1528. "delete_{$capability_type}",
  1529. "edit_{$capability_ty…

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