WC_Product

Abstract Product Class.

Defined (1)

The class is defined in the following location(s).

/includes/abstracts/abstract-wc-product.php  
  1. class WC_Product extends WC_Abstract_Legacy_Product { 
  2.  
  3. /** 
  4. * This is the name of this object type. 
  5. * @var string 
  6. */ 
  7. protected $object_type = 'product'; 
  8.  
  9. /** 
  10. * Post type. 
  11. * @var string 
  12. */ 
  13. protected $post_type = 'product'; 
  14.  
  15. /** 
  16. * Cache group. 
  17. * @var string 
  18. */ 
  19. protected $cache_group = 'products'; 
  20.  
  21. /** 
  22. * Stores product data. 
  23. * @var array 
  24. */ 
  25. protected $data = array( 
  26. 'name' => '',  
  27. 'slug' => '',  
  28. 'date_created' => null,  
  29. 'date_modified' => null,  
  30. 'status' => false,  
  31. 'featured' => false,  
  32. 'catalog_visibility' => 'visible',  
  33. 'description' => '',  
  34. 'short_description' => '',  
  35. 'sku' => '',  
  36. 'price' => '',  
  37. 'regular_price' => '',  
  38. 'sale_price' => '',  
  39. 'date_on_sale_from' => null,  
  40. 'date_on_sale_to' => null,  
  41. 'total_sales' => '0',  
  42. 'tax_status' => 'taxable',  
  43. 'tax_class' => '',  
  44. 'manage_stock' => false,  
  45. 'stock_quantity' => null,  
  46. 'stock_status' => 'instock',  
  47. 'backorders' => 'no',  
  48. 'sold_individually' => false,  
  49. 'weight' => '',  
  50. 'length' => '',  
  51. 'width' => '',  
  52. 'height' => '',  
  53. 'upsell_ids' => array(),  
  54. 'cross_sell_ids' => array(),  
  55. 'parent_id' => 0,  
  56. 'reviews_allowed' => true,  
  57. 'purchase_note' => '',  
  58. 'attributes' => array(),  
  59. 'default_attributes' => array(),  
  60. 'menu_order' => 0,  
  61. 'virtual' => false,  
  62. 'downloadable' => false,  
  63. 'category_ids' => array(),  
  64. 'tag_ids' => array(),  
  65. 'shipping_class_id' => 0,  
  66. 'downloads' => array(),  
  67. 'image_id' => '',  
  68. 'gallery_image_ids' => array(),  
  69. 'download_limit' => -1,  
  70. 'download_expiry' => -1,  
  71. 'rating_counts' => array(),  
  72. 'average_rating' => 0,  
  73. 'review_count' => 0,  
  74. ); 
  75.  
  76. /** 
  77. * Supported features such as 'ajax_add_to_cart'. 
  78. * @var array 
  79. */ 
  80. protected $supports = array(); 
  81.  
  82. /** 
  83. * Get the product if ID is passed, otherwise the product is new and empty. 
  84. * This class should NOT be instantiated, but the wc_get_product() function 
  85. * should be used. It is possible, but the wc_get_product() is preferred. 
  86. * @param int|WC_Product|object $product Product to init. 
  87. */ 
  88. public function __construct( $product = 0 ) { 
  89. parent::__construct( $product ); 
  90. if ( is_numeric( $product ) && $product > 0 ) { 
  91. $this->set_id( $product ); 
  92. } elseif ( $product instanceof self ) { 
  93. $this->set_id( absint( $product->get_id() ) ); 
  94. } elseif ( ! empty( $product->ID ) ) { 
  95. $this->set_id( absint( $product->ID ) ); 
  96. } else { 
  97. $this->set_object_read( true ); 
  98.  
  99. $this->data_store = WC_Data_Store::load( 'product-' . $this->get_type() ); 
  100. if ( $this->get_id() > 0 ) { 
  101. $this->data_store->read( $this ); 
  102.  
  103. /** 
  104. * Get internal type. Should return string and *should be overridden* by child classes. 
  105. * The product_type property is deprecated but is used here for BW compat with child classes which may be defining product_type and not have a get_type method. 
  106. * @since 3.0.0 
  107. * @return string 
  108. */ 
  109. public function get_type() { 
  110. return isset( $this->product_type ) ? $this->product_type : 'simple'; 
  111.  
  112. /** 
  113. |-------------------------------------------------------------------------- 
  114. | Getters 
  115. |-------------------------------------------------------------------------- 
  116. | Methods for getting data from the product object. 
  117. */ 
  118.  
  119. /** 
  120. * Get product name. 
  121. * @since 3.0.0 
  122. * @param string $context 
  123. * @return string 
  124. */ 
  125. public function get_name( $context = 'view' ) { 
  126. return $this->get_prop( 'name', $context ); 
  127.  
  128. /** 
  129. * Get product slug. 
  130. * @since 3.0.0 
  131. * @param string $context 
  132. * @return string 
  133. */ 
  134. public function get_slug( $context = 'view' ) { 
  135. return $this->get_prop( 'slug', $context ); 
  136.  
  137. /** 
  138. * Get product created date. 
  139. * @since 3.0.0 
  140. * @param string $context 
  141. * @return WC_DateTime|NULL object if the date is set or null if there is no date. 
  142. */ 
  143. public function get_date_created( $context = 'view' ) { 
  144. return $this->get_prop( 'date_created', $context ); 
  145.  
  146. /** 
  147. * Get product modified date. 
  148. * @since 3.0.0 
  149. * @param string $context 
  150. * @return WC_DateTime|NULL object if the date is set or null if there is no date. 
  151. */ 
  152. public function get_date_modified( $context = 'view' ) { 
  153. return $this->get_prop( 'date_modified', $context ); 
  154.  
  155. /** 
  156. * Get product status. 
  157. * @since 3.0.0 
  158. * @param string $context 
  159. * @return string 
  160. */ 
  161. public function get_status( $context = 'view' ) { 
  162. return $this->get_prop( 'status', $context ); 
  163.  
  164. /** 
  165. * If the product is featured. 
  166. * @since 3.0.0 
  167. * @param string $context 
  168. * @return boolean 
  169. */ 
  170. public function get_featured( $context = 'view' ) { 
  171. return $this->get_prop( 'featured', $context ); 
  172.  
  173. /** 
  174. * Get catalog visibility. 
  175. * @since 3.0.0 
  176. * @param string $context 
  177. * @return string 
  178. */ 
  179. public function get_catalog_visibility( $context = 'view' ) { 
  180. return $this->get_prop( 'catalog_visibility', $context ); 
  181.  
  182. /** 
  183. * Get product description. 
  184. * @since 3.0.0 
  185. * @param string $context 
  186. * @return string 
  187. */ 
  188. public function get_description( $context = 'view' ) { 
  189. return $this->get_prop( 'description', $context ); 
  190.  
  191. /** 
  192. * Get product short description. 
  193. * @since 3.0.0 
  194. * @param string $context 
  195. * @return string 
  196. */ 
  197. public function get_short_description( $context = 'view' ) { 
  198. return $this->get_prop( 'short_description', $context ); 
  199.  
  200. /** 
  201. * Get SKU (Stock-keeping unit) - product unique ID. 
  202. * @param string $context 
  203. * @return string 
  204. */ 
  205. public function get_sku( $context = 'view' ) { 
  206. return $this->get_prop( 'sku', $context ); 
  207.  
  208. /** 
  209. * Returns the product's active price. 
  210. * @param string $context 
  211. * @return string price 
  212. */ 
  213. public function get_price( $context = 'view' ) { 
  214. return $this->get_prop( 'price', $context ); 
  215.  
  216. /** 
  217. * Returns the product's regular price. 
  218. * @param string $context 
  219. * @return string price 
  220. */ 
  221. public function get_regular_price( $context = 'view' ) { 
  222. return $this->get_prop( 'regular_price', $context ); 
  223.  
  224. /** 
  225. * Returns the product's sale price. 
  226. * @param string $context 
  227. * @return string price 
  228. */ 
  229. public function get_sale_price( $context = 'view' ) { 
  230. return $this->get_prop( 'sale_price', $context ); 
  231.  
  232. /** 
  233. * Get date on sale from. 
  234. * @since 3.0.0 
  235. * @param string $context 
  236. * @return WC_DateTime|NULL object if the date is set or null if there is no date. 
  237. */ 
  238. public function get_date_on_sale_from( $context = 'view' ) { 
  239. return $this->get_prop( 'date_on_sale_from', $context ); 
  240.  
  241. /** 
  242. * Get date on sale to. 
  243. * @since 3.0.0 
  244. * @param string $context 
  245. * @return WC_DateTime|NULL object if the date is set or null if there is no date. 
  246. */ 
  247. public function get_date_on_sale_to( $context = 'view' ) { 
  248. return $this->get_prop( 'date_on_sale_to', $context ); 
  249.  
  250. /** 
  251. * Get number total of sales. 
  252. * @since 3.0.0 
  253. * @param string $context 
  254. * @return int 
  255. */ 
  256. public function get_total_sales( $context = 'view' ) { 
  257. return $this->get_prop( 'total_sales', $context ); 
  258.  
  259. /** 
  260. * Returns the tax status. 
  261. * @param string $context 
  262. * @return string 
  263. */ 
  264. public function get_tax_status( $context = 'view' ) { 
  265. return $this->get_prop( 'tax_status', $context ); 
  266.  
  267. /** 
  268. * Returns the tax class. 
  269. * @param string $context 
  270. * @return string 
  271. */ 
  272. public function get_tax_class( $context = 'view' ) { 
  273. return $this->get_prop( 'tax_class', $context ); 
  274.  
  275. /** 
  276. * Return if product manage stock. 
  277. * @since 3.0.0 
  278. * @param string $context 
  279. * @return boolean 
  280. */ 
  281. public function get_manage_stock( $context = 'view' ) { 
  282. return $this->get_prop( 'manage_stock', $context ); 
  283.  
  284. /** 
  285. * Returns number of items available for sale. 
  286. * @param string $context 
  287. * @return int|null 
  288. */ 
  289. public function get_stock_quantity( $context = 'view' ) { 
  290. return $this->get_prop( 'stock_quantity', $context ); 
  291.  
  292. /** 
  293. * Return the stock status. 
  294. * @param string $context 
  295. * @since 3.0.0 
  296. * @return string 
  297. */ 
  298. public function get_stock_status( $context = 'view' ) { 
  299. return $this->get_prop( 'stock_status', $context ); 
  300.  
  301. /** 
  302. * Get backorders. 
  303. * @param string $context 
  304. * @since 3.0.0 
  305. * @return string yes no or notify 
  306. */ 
  307. public function get_backorders( $context = 'view' ) { 
  308. return $this->get_prop( 'backorders', $context ); 
  309.  
  310. /** 
  311. * Return if should be sold individually. 
  312. * @param string $context 
  313. * @since 3.0.0 
  314. * @return boolean 
  315. */ 
  316. public function get_sold_individually( $context = 'view' ) { 
  317. return $this->get_prop( 'sold_individually', $context ); 
  318.  
  319. /** 
  320. * Returns the product's weight. 
  321. * @param string $context 
  322. * @return string 
  323. */ 
  324. public function get_weight( $context = 'view' ) { 
  325. return $this->get_prop( 'weight', $context ); 
  326.  
  327. /** 
  328. * Returns the product length. 
  329. * @param string $context 
  330. * @return string 
  331. */ 
  332. public function get_length( $context = 'view' ) { 
  333. return $this->get_prop( 'length', $context ); 
  334.  
  335. /** 
  336. * Returns the product width. 
  337. * @param string $context 
  338. * @return string 
  339. */ 
  340. public function get_width( $context = 'view' ) { 
  341. return $this->get_prop( 'width', $context ); 
  342.  
  343. /** 
  344. * Returns the product height. 
  345. * @param string $context 
  346. * @return string 
  347. */ 
  348. public function get_height( $context = 'view' ) { 
  349. return $this->get_prop( 'height', $context ); 
  350.  
  351. /** 
  352. * Returns formatted dimensions. 
  353. * @param $formatted True by default for legacy support - will be false/not set in future versions to return the array only. Use wc_format_dimensions for formatted versions instead. 
  354. * @return string|array 
  355. */ 
  356. public function get_dimensions( $formatted = true ) { 
  357. if ( $formatted ) { 
  358. wc_deprecated_argument( 'WC_Product::get_dimensions', '3.0', 'By default, get_dimensions has an argument set to true so that HTML is returned. This is to support the legacy version of the method. To get HTML dimensions, instead use wc_format_dimensions() function. Pass false to this method to return an array of dimensions. This will be the new default behavior in future versions.' ); 
  359. return apply_filters( 'woocommerce_product_dimensions', wc_format_dimensions( $this->get_dimensions( false ) ), $this ); 
  360. return array( 
  361. 'length' => $this->get_length(),  
  362. 'width' => $this->get_width(),  
  363. 'height' => $this->get_height(),  
  364. ); 
  365.  
  366. /** 
  367. * Get upsel IDs. 
  368. * @since 3.0.0 
  369. * @param string $context 
  370. * @return array 
  371. */ 
  372. public function get_upsell_ids( $context = 'view' ) { 
  373. return $this->get_prop( 'upsell_ids', $context ); 
  374.  
  375. /** 
  376. * Get cross sell IDs. 
  377. * @since 3.0.0 
  378. * @param string $context 
  379. * @return array 
  380. */ 
  381. public function get_cross_sell_ids( $context = 'view' ) { 
  382. return $this->get_prop( 'cross_sell_ids', $context ); 
  383.  
  384. /** 
  385. * Get parent ID. 
  386. * @since 3.0.0 
  387. * @param string $context 
  388. * @return int 
  389. */ 
  390. public function get_parent_id( $context = 'view' ) { 
  391. return $this->get_prop( 'parent_id', $context ); 
  392.  
  393. /** 
  394. * Return if reviews is allowed. 
  395. * @since 3.0.0 
  396. * @param string $context 
  397. * @return bool 
  398. */ 
  399. public function get_reviews_allowed( $context = 'view' ) { 
  400. return $this->get_prop( 'reviews_allowed', $context ); 
  401.  
  402. /** 
  403. * Get purchase note. 
  404. * @since 3.0.0 
  405. * @param string $context 
  406. * @return string 
  407. */ 
  408. public function get_purchase_note( $context = 'view' ) { 
  409. return $this->get_prop( 'purchase_note', $context ); 
  410.  
  411. /** 
  412. * Returns product attributes. 
  413. * @param string $context 
  414. * @return array 
  415. */ 
  416. public function get_attributes( $context = 'view' ) { 
  417. return $this->get_prop( 'attributes', $context ); 
  418.  
  419. /** 
  420. * Get default attributes. 
  421. * @since 3.0.0 
  422. * @param string $context 
  423. * @return array 
  424. */ 
  425. public function get_default_attributes( $context = 'view' ) { 
  426. return $this->get_prop( 'default_attributes', $context ); 
  427.  
  428. /** 
  429. * Get menu order. 
  430. * @since 3.0.0 
  431. * @param string $context 
  432. * @return int 
  433. */ 
  434. public function get_menu_order( $context = 'view' ) { 
  435. return $this->get_prop( 'menu_order', $context ); 
  436.  
  437. /** 
  438. * Get category ids. 
  439. * @since 3.0.0 
  440. * @param string $context 
  441. * @return array 
  442. */ 
  443. public function get_category_ids( $context = 'view' ) { 
  444. return $this->get_prop( 'category_ids', $context ); 
  445.  
  446. /** 
  447. * Get tag ids. 
  448. * @since 3.0.0 
  449. * @param string $context 
  450. * @return array 
  451. */ 
  452. public function get_tag_ids( $context = 'view' ) { 
  453. return $this->get_prop( 'tag_ids', $context ); 
  454.  
  455. /** 
  456. * Get virtual. 
  457. * @since 3.0.0 
  458. * @param string $context 
  459. * @return bool 
  460. */ 
  461. public function get_virtual( $context = 'view' ) { 
  462. return $this->get_prop( 'virtual', $context ); 
  463.  
  464. /** 
  465. * Returns the gallery attachment ids. 
  466. * @param string $context 
  467. * @return array 
  468. */ 
  469. public function get_gallery_image_ids( $context = 'view' ) { 
  470. return $this->get_prop( 'gallery_image_ids', $context ); 
  471.  
  472. /** 
  473. * Get shipping class ID. 
  474. * @since 3.0.0 
  475. * @param string $context 
  476. * @return int 
  477. */ 
  478. public function get_shipping_class_id( $context = 'view' ) { 
  479. return $this->get_prop( 'shipping_class_id', $context ); 
  480.  
  481. /** 
  482. * Get downloads. 
  483. * @since 3.0.0 
  484. * @param string $context 
  485. * @return array 
  486. */ 
  487. public function get_downloads( $context = 'view' ) { 
  488. return $this->get_prop( 'downloads', $context ); 
  489.  
  490. /** 
  491. * Get download expiry. 
  492. * @since 3.0.0 
  493. * @param string $context 
  494. * @return int 
  495. */ 
  496. public function get_download_expiry( $context = 'view' ) { 
  497. return $this->get_prop( 'download_expiry', $context ); 
  498.  
  499. /** 
  500. * Get downloadable. 
  501. * @since 3.0.0 
  502. * @param string $context 
  503. * @return bool 
  504. */ 
  505. public function get_downloadable( $context = 'view' ) { 
  506. return $this->get_prop( 'downloadable', $context ); 
  507.  
  508. /** 
  509. * Get download limit. 
  510. * @since 3.0.0 
  511. * @param string $context 
  512. * @return int 
  513. */ 
  514. public function get_download_limit( $context = 'view' ) { 
  515. return $this->get_prop( 'download_limit', $context ); 
  516.  
  517. /** 
  518. * Get main image ID. 
  519. * @since 3.0.0 
  520. * @param string $context 
  521. * @return string 
  522. */ 
  523. public function get_image_id( $context = 'view' ) { 
  524. return $this->get_prop( 'image_id', $context ); 
  525.  
  526. /** 
  527. * Get rating count. 
  528. * @param string $context 
  529. * @return array of counts 
  530. */ 
  531. public function get_rating_counts( $context = 'view' ) { 
  532. return $this->get_prop( 'rating_counts', $context ); 
  533.  
  534. /** 
  535. * Get average rating. 
  536. * @param string $context 
  537. * @return float 
  538. */ 
  539. public function get_average_rating( $context = 'view' ) { 
  540. return $this->get_prop( 'average_rating', $context ); 
  541.  
  542. /** 
  543. * Get review count. 
  544. * @param string $context 
  545. * @return int 
  546. */ 
  547. public function get_review_count( $context = 'view' ) { 
  548. return $this->get_prop( 'review_count', $context ); 
  549.  
  550. /** 
  551. |-------------------------------------------------------------------------- 
  552. | Setters 
  553. |-------------------------------------------------------------------------- 
  554. | Functions for setting product data. These should not update anything in the 
  555. | database itself and should only change what is stored in the class 
  556. | object. 
  557. */ 
  558.  
  559. /** 
  560. * Set product name. 
  561. * @since 3.0.0 
  562. * @param string $name Product name. 
  563. */ 
  564. public function set_name( $name ) { 
  565. $this->set_prop( 'name', $name ); 
  566.  
  567. /** 
  568. * Set product slug. 
  569. * @since 3.0.0 
  570. * @param string $slug Product slug. 
  571. */ 
  572. public function set_slug( $slug ) { 
  573. $this->set_prop( 'slug', $slug ); 
  574.  
  575. /** 
  576. * Set product created date. 
  577. * @since 3.0.0 
  578. * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. 
  579. */ 
  580. public function set_date_created( $date = null ) { 
  581. $this->set_date_prop( 'date_created', $date ); 
  582.  
  583. /** 
  584. * Set product modified date. 
  585. * @since 3.0.0 
  586. * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. 
  587. */ 
  588. public function set_date_modified( $date = null ) { 
  589. $this->set_date_prop( 'date_modified', $date ); 
  590.  
  591. /** 
  592. * Set product status. 
  593. * @since 3.0.0 
  594. * @param string $status Product status. 
  595. */ 
  596. public function set_status( $status ) { 
  597. $this->set_prop( 'status', $status ); 
  598.  
  599. /** 
  600. * Set if the product is featured. 
  601. * @since 3.0.0 
  602. * @param bool|string 
  603. */ 
  604. public function set_featured( $featured ) { 
  605. $this->set_prop( 'featured', wc_string_to_bool( $featured ) ); 
  606.  
  607. /** 
  608. * Set catalog visibility. 
  609. * @since 3.0.0 
  610. * @throws WC_Data_Exception 
  611. * @param string $visibility Options: 'hidden', 'visible', 'search' and 'catalog'. 
  612. */ 
  613. public function set_catalog_visibility( $visibility ) { 
  614. $options = array_keys( wc_get_product_visibility_options() ); 
  615. if ( ! in_array( $visibility, $options, true ) ) { 
  616. $this->error( 'product_invalid_catalog_visibility', __( 'Invalid catalog visibility option.', 'woocommerce' ) ); 
  617. $this->set_prop( 'catalog_visibility', $visibility ); 
  618.  
  619. /** 
  620. * Set product description. 
  621. * @since 3.0.0 
  622. * @param string $description Product description. 
  623. */ 
  624. public function set_description( $description ) { 
  625. $this->set_prop( 'description', $description ); 
  626.  
  627. /** 
  628. * Set product short description. 
  629. * @since 3.0.0 
  630. * @param string $short_description Product short description. 
  631. */ 
  632. public function set_short_description( $short_description ) { 
  633. $this->set_prop( 'short_description', $short_description ); 
  634.  
  635. /** 
  636. * Set SKU. 
  637. * @since 3.0.0 
  638. * @throws WC_Data_Exception 
  639. * @param string $sku Product SKU. 
  640. */ 
  641. public function set_sku( $sku ) { 
  642. $sku = (string) $sku; 
  643. if ( $this->get_object_read() && ! empty( $sku ) && ! wc_product_has_unique_sku( $this->get_id(), $sku ) ) { 
  644. $sku_found = wc_get_product_id_by_sku( $sku ); 
  645.  
  646. $this->error( 'product_invalid_sku', __( 'Invalid or duplicated SKU.', 'woocommerce' ), 400, array( 'resource_id' => $sku_found ) ); 
  647. $this->set_prop( 'sku', $sku ); 
  648.  
  649. /** 
  650. * Set the product's active price. 
  651. * @param string $price Price. 
  652. */ 
  653. public function set_price( $price ) { 
  654. $this->set_prop( 'price', wc_format_decimal( $price ) ); 
  655.  
  656. /** 
  657. * Set the product's regular price. 
  658. * @since 3.0.0 
  659. * @param string $price Regular price. 
  660. */ 
  661. public function set_regular_price( $price ) { 
  662. $this->set_prop( 'regular_price', wc_format_decimal( $price ) ); 
  663.  
  664. /** 
  665. * Set the product's sale price. 
  666. * @since 3.0.0 
  667. * @param string $price sale price. 
  668. */ 
  669. public function set_sale_price( $price ) { 
  670. $this->set_prop( 'sale_price', wc_format_decimal( $price ) ); 
  671.  
  672. /** 
  673. * Set date on sale from. 
  674. * @since 3.0.0 
  675. * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. 
  676. */ 
  677. public function set_date_on_sale_from( $date = null ) { 
  678. $this->set_date_prop( 'date_on_sale_from', $date ); 
  679.  
  680. /** 
  681. * Set date on sale to. 
  682. * @since 3.0.0 
  683. * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. 
  684. */ 
  685. public function set_date_on_sale_to( $date = null ) { 
  686. $this->set_date_prop( 'date_on_sale_to', $date ); 
  687.  
  688. /** 
  689. * Set number total of sales. 
  690. * @since 3.0.0 
  691. * @param int $total Total of sales. 
  692. */ 
  693. public function set_total_sales( $total ) { 
  694. $this->set_prop( 'total_sales', absint( $total ) ); 
  695.  
  696. /** 
  697. * Set the tax status. 
  698. * @since 3.0.0 
  699. * @throws WC_Data_Exception 
  700. * @param string $status Tax status. 
  701. */ 
  702. public function set_tax_status( $status ) { 
  703. $options = array( 
  704. 'taxable',  
  705. 'shipping',  
  706. 'none',  
  707. ); 
  708.  
  709. // Set default if empty. 
  710. if ( empty( $status ) ) { 
  711. $status = 'taxable'; 
  712.  
  713. if ( ! in_array( $status, $options, true ) ) { 
  714. $this->error( 'product_invalid_tax_status', __( 'Invalid product tax status.', 'woocommerce' ) ); 
  715.  
  716. $this->set_prop( 'tax_status', $status ); 
  717.  
  718. /** 
  719. * Set the tax class. 
  720. * @since 3.0.0 
  721. * @param string $class Tax class. 
  722. */ 
  723. public function set_tax_class( $class ) { 
  724. $class = sanitize_title( $class ); 
  725. $class = 'standard' === $class ? '' : $class; 
  726. $this->set_prop( 'tax_class', $class ); 
  727.  
  728. /** 
  729. * Set if product manage stock. 
  730. * @since 3.0.0 
  731. * @param bool 
  732. */ 
  733. public function set_manage_stock( $manage_stock ) { 
  734. $this->set_prop( 'manage_stock', wc_string_to_bool( $manage_stock ) ); 
  735.  
  736. /** 
  737. * Set number of items available for sale. 
  738. * @since 3.0.0 
  739. * @param float|null $quantity Stock quantity. 
  740. */ 
  741. public function set_stock_quantity( $quantity ) { 
  742. $this->set_prop( 'stock_quantity', '' !== $quantity ? wc_stock_amount( $quantity ) : null ); 
  743.  
  744. /** 
  745. * Set stock status. 
  746. * @param string $status New status. 
  747. */ 
  748. public function set_stock_status( $status = '' ) { 
  749. $this->set_prop( 'stock_status', 'outofstock' === $status ? 'outofstock' : 'instock' ); 
  750.  
  751. /** 
  752. * Set backorders. 
  753. * @since 3.0.0 
  754. * @param string $backorders Options: 'yes', 'no' or 'notify'. 
  755. */ 
  756. public function set_backorders( $backorders ) { 
  757. $this->set_prop( 'backorders', $backorders ); 
  758.  
  759. /** 
  760. * Set if should be sold individually. 
  761. * @since 3.0.0 
  762. * @param bool 
  763. */ 
  764. public function set_sold_individually( $sold_individually ) { 
  765. $this->set_prop( 'sold_individually', wc_string_to_bool( $sold_individually ) ); 
  766.  
  767. /** 
  768. * Set the product's weight. 
  769. * @since 3.0.0 
  770. * @param float|string $weight Total weight. 
  771. */ 
  772. public function set_weight( $weight ) { 
  773. $this->set_prop( 'weight', '' === $weight ? '' : wc_format_decimal( $weight ) ); 
  774.  
  775. /** 
  776. * Set the product length. 
  777. * @since 3.0.0 
  778. * @param float|string $length Total length. 
  779. */ 
  780. public function set_length( $length ) { 
  781. $this->set_prop( 'length', '' === $length ? '' : wc_format_decimal( $length ) ); 
  782.  
  783. /** 
  784. * Set the product width. 
  785. * @since 3.0.0 
  786. * @param float|string $width Total width. 
  787. */ 
  788. public function set_width( $width ) { 
  789. $this->set_prop( 'width', '' === $width ? '' : wc_format_decimal( $width ) ); 
  790.  
  791. /** 
  792. * Set the product height. 
  793. * @since 3.0.0 
  794. * @param float|string $height Total height. 
  795. */ 
  796. public function set_height( $height ) { 
  797. $this->set_prop( 'height', '' === $height ? '' : wc_format_decimal( $height ) ); 
  798.  
  799. /** 
  800. * Set upsell IDs. 
  801. * @since 3.0.0 
  802. * @param array $upsell_ids IDs from the up-sell products. 
  803. */ 
  804. public function set_upsell_ids( $upsell_ids ) { 
  805. $this->set_prop( 'upsell_ids', array_filter( (array) $upsell_ids ) ); 
  806.  
  807. /** 
  808. * Set crosssell IDs. 
  809. * @since 3.0.0 
  810. * @param array $cross_sell_ids IDs from the cross-sell products. 
  811. */ 
  812. public function set_cross_sell_ids( $cross_sell_ids ) { 
  813. $this->set_prop( 'cross_sell_ids', array_filter( (array) $cross_sell_ids ) ); 
  814.  
  815. /** 
  816. * Set parent ID. 
  817. * @since 3.0.0 
  818. * @param int $parent_id Product parent ID. 
  819. */ 
  820. public function set_parent_id( $parent_id ) { 
  821. $this->set_prop( 'parent_id', absint( $parent_id ) ); 
  822.  
  823. /** 
  824. * Set if reviews is allowed. 
  825. * @since 3.0.0 
  826. * @param bool $reviews_allowed Reviews allowed or not. 
  827. */ 
  828. public function set_reviews_allowed( $reviews_allowed ) { 
  829. $this->set_prop( 'reviews_allowed', wc_string_to_bool( $reviews_allowed ) ); 
  830.  
  831. /** 
  832. * Set purchase note. 
  833. * @since 3.0.0 
  834. * @param string $purchase_note Purchase note. 
  835. */ 
  836. public function set_purchase_note( $purchase_note ) { 
  837. $this->set_prop( 'purchase_note', $purchase_note ); 
  838.  
  839. /** 
  840. * Set product attributes. 
  841. * Attributes are made up of: 
  842. * id - 0 for product level attributes. ID for global attributes. 
  843. * name - Attribute name. 
  844. * options - attribute value or array of term ids/names. 
  845. * position - integer sort order. 
  846. * visible - If visible on frontend. 
  847. * variation - If used for variations. 
  848. * Indexed by unqiue key to allow clearing old ones after a set. 
  849. * @since 3.0.0 
  850. * @param array $raw_attributes Array of WC_Product_Attribute objects. 
  851. */ 
  852. public function set_attributes( $raw_attributes ) { 
  853. $attributes = array_fill_keys( array_keys( $this->get_attributes( 'edit' ) ), null ); 
  854. foreach ( $raw_attributes as $attribute ) { 
  855. if ( is_a( $attribute, 'WC_Product_Attribute' ) ) { 
  856. $attributes[ sanitize_title( $attribute->get_name() ) ] = $attribute; 
  857.  
  858. uasort( $attributes, 'wc_product_attribute_uasort_comparison' ); 
  859. $this->set_prop( 'attributes', $attributes ); 
  860.  
  861. /** 
  862. * Set default attributes. 
  863. * @since 3.0.0 
  864. * @param array $default_attributes List of default attributes. 
  865. */ 
  866. public function set_default_attributes( $default_attributes ) { 
  867. $this->set_prop( 'default_attributes', array_filter( (array) $default_attributes ) ); 
  868.  
  869. /** 
  870. * Set menu order. 
  871. * @since 3.0.0 
  872. * @param int $menu_order Menu order. 
  873. */ 
  874. public function set_menu_order( $menu_order ) { 
  875. $this->set_prop( 'menu_order', intval( $menu_order ) ); 
  876.  
  877. /** 
  878. * Set the product categories. 
  879. * @since 3.0.0 
  880. * @param array $term_ids List of terms IDs. 
  881. */ 
  882. public function set_category_ids( $term_ids ) { 
  883. $this->set_prop( 'category_ids', array_unique( array_map( 'intval', $term_ids ) ) ); 
  884.  
  885. /** 
  886. * Set the product tags. 
  887. * @since 3.0.0 
  888. * @param array $term_ids List of terms IDs. 
  889. */ 
  890. public function set_tag_ids( $term_ids ) { 
  891. $this->set_prop( 'tag_ids', array_unique( array_map( 'intval', $term_ids ) ) ); 
  892.  
  893. /** 
  894. * Set if the product is virtual. 
  895. * @since 3.0.0 
  896. * @param bool|string 
  897. */ 
  898. public function set_virtual( $virtual ) { 
  899. $this->set_prop( 'virtual', wc_string_to_bool( $virtual ) ); 
  900.  
  901. /** 
  902. * Set shipping class ID. 
  903. * @since 3.0.0 
  904. * @param int 
  905. */ 
  906. public function set_shipping_class_id( $id ) { 
  907. $this->set_prop( 'shipping_class_id', absint( $id ) ); 
  908.  
  909. /** 
  910. * Set if the product is downloadable. 
  911. * @since 3.0.0 
  912. * @param bool|string 
  913. */ 
  914. public function set_downloadable( $downloadable ) { 
  915. $this->set_prop( 'downloadable', wc_string_to_bool( $downloadable ) ); 
  916.  
  917. /** 
  918. * Set downloads. 
  919. * @since 3.0.0 
  920. * @param $downloads_array array of WC_Product_Download objects or arrays. 
  921. */ 
  922. public function set_downloads( $downloads_array ) { 
  923. $downloads = array(); 
  924. $errors = array(); 
  925.  
  926. foreach ( $downloads_array as $download ) { 
  927. if ( is_a( $download, 'WC_Product_Download' ) ) { 
  928. $download_object = $download; 
  929. } else { 
  930. $download_object = new WC_Product_Download(); 
  931. $download['previous_hash'] = isset( $download['previous_hash'] ) ? $download['previous_hash'] : ''; 
  932. $file_hash = apply_filters( 'woocommerce_downloadable_file_hash', md5( $download['file'] ), $this->get_id(), $download['name'], $download['file'], $download['previous_hash'] ); 
  933.  
  934. $download_object->set_id( $file_hash ); 
  935. $download_object->set_name( $download['name'] ); 
  936. $download_object->set_file( $download['file'] ); 
  937. $download_object->set_previous_hash( $download['previous_hash'] ); 
  938.  
  939. // Validate the file extension 
  940. if ( ! $download_object->is_allowed_filetype() ) { 
  941. if ( $this->get_object_read() ) { 
  942. $errors[] = sprintf( __( 'The downloadable file %1$s cannot be used as it does not have an allowed file type. Allowed types include: %2$s', 'woocommerce' ), '<code>' . basename( $download_object->get_file() ) . '</code>', '<code>' . implode( ', ', array_keys( $download_object->get_allowed_mime_types() ) ) . '</code>' ); 
  943. continue; 
  944.  
  945. // Validate the file exists. 
  946. if ( ! $download_object->file_exists() ) { 
  947. if ( $this->get_object_read() ) { 
  948. $errors[] = sprintf( __( 'The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce' ), '<code>' . $download_object->get_file() . '</code>' ); 
  949. continue; 
  950.  
  951. $downloads[ $download_object->get_id() ] = $download_object; 
  952.  
  953. if ( $errors ) { 
  954. $this->error( 'product_invalid_download', $errors[0] ); 
  955.  
  956. $this->set_prop( 'downloads', $downloads ); 
  957.  
  958. /** 
  959. * Set download limit. 
  960. * @since 3.0.0 
  961. * @param int $download_limit 
  962. */ 
  963. public function set_download_limit( $download_limit ) { 
  964. $this->set_prop( 'download_limit', -1 === (int) $download_limit || '' === $download_limit ? -1 : absint( $download_limit ) ); 
  965.  
  966. /** 
  967. * Set download expiry. 
  968. * @since 3.0.0 
  969. * @param int $download_expiry 
  970. */ 
  971. public function set_download_expiry( $download_expiry ) { 
  972. $this->set_prop( 'download_expiry', -1 === (int) $download_expiry || '' === $download_expiry ? -1 : absint( $download_expiry ) ); 
  973.  
  974. /** 
  975. * Set gallery attachment ids. 
  976. * @since 3.0.0 
  977. * @param array $image_ids 
  978. */ 
  979. public function set_gallery_image_ids( $image_ids ) { 
  980. $image_ids = wp_parse_id_list( $image_ids ); 
  981.  
  982. if ( $this->get_object_read() ) { 
  983. $image_ids = array_filter( $image_ids, 'wp_attachment_is_image' ); 
  984.  
  985. $this->set_prop( 'gallery_image_ids', $image_ids ); 
  986.  
  987. /** 
  988. * Set main image ID. 
  989. * @since 3.0.0 
  990. * @param int $image_id 
  991. */ 
  992. public function set_image_id( $image_id = '' ) { 
  993. $this->set_prop( 'image_id', $image_id ); 
  994.  
  995. /** 
  996. * Set rating counts. Read only. 
  997. * @param array $counts 
  998. */ 
  999. public function set_rating_counts( $counts ) { 
  1000. $this->set_prop( 'rating_counts', array_filter( array_map( 'absint', (array) $counts ) ) ); 
  1001.  
  1002. /** 
  1003. * Set average rating. Read only. 
  1004. * @param float $average 
  1005. */ 
  1006. public function set_average_rating( $average ) { 
  1007. $this->set_prop( 'average_rating', wc_format_decimal( $average ) ); 
  1008.  
  1009. /** 
  1010. * Set review count. Read only. 
  1011. * @param int $count 
  1012. */ 
  1013. public function set_review_count( $count ) { 
  1014. $this->set_prop( 'review_count', absint( $count ) ); 
  1015.  
  1016. /** 
  1017. |-------------------------------------------------------------------------- 
  1018. | Other Methods 
  1019. |-------------------------------------------------------------------------- 
  1020. */ 
  1021.  
  1022. /** 
  1023. * Ensure properties are set correctly before save. 
  1024. * @since 3.0.0 
  1025. */ 
  1026. public function validate_props() { 
  1027. // Before updating, ensure stock props are all aligned. Qty and backorders are not needed if not stock managed. 
  1028. if ( ! $this->get_manage_stock() ) { 
  1029. $this->set_stock_quantity( '' ); 
  1030. $this->set_backorders( 'no' ); 
  1031.  
  1032. // If we are stock managing and we don't have stock, force out of stock status. 
  1033. } elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount' ) && 'no' === $this->get_backorders() ) { 
  1034. $this->set_stock_status( 'outofstock' ); 
  1035.  
  1036. // If the stock level is changing and we do now have enough, force in stock status. 
  1037. } elseif ( $this->get_stock_quantity() > get_option( 'woocommerce_notify_no_stock_amount' ) && array_key_exists( 'stock_quantity', $this->get_changes() ) ) { 
  1038. $this->set_stock_status( 'instock' ); 
  1039.  
  1040. /** 
  1041. * Save data (either create or update depending on if we are working on an existing product). 
  1042. * @since 3.0.0 
  1043. */ 
  1044. public function save() { 
  1045. $this->validate_props(); 
  1046.  
  1047. if ( $this->data_store ) { 
  1048. // Trigger action before saving to the DB. Use a pointer to adjust object props before save. 
  1049. do_action( 'woocommerce_before_' . $this->object_type . '_object_save', $this, $this->data_store ); 
  1050.  
  1051. if ( $this->get_id() ) { 
  1052. $this->data_store->update( $this ); 
  1053. } else { 
  1054. $this->data_store->create( $this ); 
  1055. if ( $this->get_parent_id() ) { 
  1056. wc_deferred_product_sync( $this->get_parent_id() ); 
  1057. return $this->get_id(); 
  1058.  
  1059. /** 
  1060. |-------------------------------------------------------------------------- 
  1061. | Conditionals 
  1062. |-------------------------------------------------------------------------- 
  1063. */ 
  1064.  
  1065. /** 
  1066. * Check if a product supports a given feature. 
  1067. * Product classes should override this to declare support (or lack of support) for a feature. 
  1068. * @param string $feature string The name of a feature to test support for. 
  1069. * @return bool True if the product supports the feature, false otherwise. 
  1070. * @since 2.5.0 
  1071. */ 
  1072. public function supports( $feature ) { 
  1073. return apply_filters( 'woocommerce_product_supports', in_array( $feature, $this->supports ) ? true : false, $feature, $this ); 
  1074.  
  1075. /** 
  1076. * Returns whether or not the product post exists. 
  1077. * @return bool 
  1078. */ 
  1079. public function exists() { 
  1080. return false !== $this->get_status(); 
  1081.  
  1082. /** 
  1083. * Checks the product type. 
  1084. * Backwards compat with downloadable/virtual. 
  1085. * @param string $type Array or string of types 
  1086. * @return bool 
  1087. */ 
  1088. public function is_type( $type ) { 
  1089. return ( $this->get_type() === $type || ( is_array( $type ) && in_array( $this->get_type(), $type ) ) ); 
  1090.  
  1091. /** 
  1092. * Checks if a product is downloadable. 
  1093. * @return bool 
  1094. */ 
  1095. public function is_downloadable() { 
  1096. return apply_filters( 'woocommerce_is_downloadable', true === $this->get_downloadable(), $this ); 
  1097.  
  1098. /** 
  1099. * Checks if a product is virtual (has no shipping). 
  1100. * @return bool 
  1101. */ 
  1102. public function is_virtual() { 
  1103. return apply_filters( 'woocommerce_is_virtual', true === $this->get_virtual(), $this ); 
  1104.  
  1105. /** 
  1106. * Returns whether or not the product is featured. 
  1107. * @return bool 
  1108. */ 
  1109. public function is_featured() { 
  1110. return true === $this->get_featured(); 
  1111.  
  1112. /** 
  1113. * Check if a product is sold individually (no quantities). 
  1114. * @return bool 
  1115. */ 
  1116. public function is_sold_individually() { 
  1117. return apply_filters( 'woocommerce_is_sold_individually', true === $this->get_sold_individually(), $this ); 
  1118.  
  1119. /** 
  1120. * Returns whether or not the product is visible in the catalog. 
  1121. * @return bool 
  1122. */ 
  1123. public function is_visible() { 
  1124. $visible = 'visible' === $this->get_catalog_visibility() || ( is_search() && 'search' === $this->get_catalog_visibility() ) || ( ! is_search() && 'catalog' === $this->get_catalog_visibility() ); 
  1125.  
  1126. if ( 'publish' !== $this->get_status() && ! current_user_can( 'edit_post', $this->get_id() ) ) { 
  1127. $visible = false; 
  1128.  
  1129. if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $this->is_in_stock() ) { 
  1130. $visible = false; 
  1131.  
  1132. return apply_filters( 'woocommerce_product_is_visible', $visible, $this->get_id() ); 
  1133.  
  1134. /** 
  1135. * Returns false if the product cannot be bought. 
  1136. * @return bool 
  1137. */ 
  1138. public function is_purchasable() { 
  1139. return apply_filters( 'woocommerce_is_purchasable', $this->exists() && ( 'publish' === $this->get_status() || current_user_can( 'edit_post', $this->get_id() ) ) && '' !== $this->get_price(), $this ); 
  1140.  
  1141. /** 
  1142. * Returns whether or not the product is on sale. 
  1143. * @param string $context What the value is for. Valid values are view and edit. 
  1144. * @return bool 
  1145. */ 
  1146. public function is_on_sale( $context = 'view' ) { 
  1147. if ( '' !== (string) $this->get_sale_price( $context ) && $this->get_regular_price( $context ) > $this->get_sale_price( $context ) ) { 
  1148. $on_sale = true; 
  1149.  
  1150. if ( $this->get_date_on_sale_from( $context ) && $this->get_date_on_sale_from( $context )->getTimestamp() > current_time( 'timestamp', true ) ) { 
  1151. $on_sale = false; 
  1152.  
  1153. if ( $this->get_date_on_sale_to( $context ) && $this->get_date_on_sale_to( $context )->getTimestamp() < current_time( 'timestamp', true ) ) { 
  1154. $on_sale = false; 
  1155. } else { 
  1156. $on_sale = false; 
  1157. return 'view' === $context ? apply_filters( 'woocommerce_product_is_on_sale', $on_sale, $this ) : $on_sale; 
  1158.  
  1159. /** 
  1160. * Returns whether or not the product has dimensions set. 
  1161. * @return bool 
  1162. */ 
  1163. public function has_dimensions() { 
  1164. return ( $this->get_length() || $this->get_height() || $this->get_width() ) && ! $this->get_virtual(); 
  1165.  
  1166. /** 
  1167. * Returns whether or not the product has weight set. 
  1168. * @return bool 
  1169. */ 
  1170. public function has_weight() { 
  1171. return $this->get_weight() && ! $this->get_virtual(); 
  1172.  
  1173. /** 
  1174. * Returns whether or not the product is in stock. 
  1175. * @return bool 
  1176. */ 
  1177. public function is_in_stock() { 
  1178. return apply_filters( 'woocommerce_product_is_in_stock', 'instock' === $this->get_stock_status(), $this ); 
  1179.  
  1180. /** 
  1181. * Checks if a product needs shipping. 
  1182. * @return bool 
  1183. */ 
  1184. public function needs_shipping() { 
  1185. return apply_filters( 'woocommerce_product_needs_shipping', ! $this->is_virtual(), $this ); 
  1186.  
  1187. /** 
  1188. * Returns whether or not the product is taxable. 
  1189. * @return bool 
  1190. */ 
  1191. public function is_taxable() { 
  1192. return apply_filters( 'woocommerce_product_is_taxable', $this->get_tax_status() === 'taxable' && wc_tax_enabled(), $this ); 
  1193.  
  1194. /** 
  1195. * Returns whether or not the product shipping is taxable. 
  1196. * @return bool 
  1197. */ 
  1198. public function is_shipping_taxable() { 
  1199. return $this->get_tax_status() === 'taxable' || $this->get_tax_status() === 'shipping'; 
  1200.  
  1201. /** 
  1202. * Returns whether or not the product is stock managed. 
  1203. * @return bool 
  1204. */ 
  1205. public function managing_stock() { 
  1206. if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) { 
  1207. return $this->get_manage_stock(); 
  1208. return false; 
  1209.  
  1210. /** 
  1211. * Returns whether or not the product can be backordered. 
  1212. * @return bool 
  1213. */ 
  1214. public function backorders_allowed() { 
  1215. return apply_filters( 'woocommerce_product_backorders_allowed', ( 'yes' === $this->get_backorders() || 'notify' === $this->get_backorders() ), $this->get_id(), $this ); 
  1216.  
  1217. /** 
  1218. * Returns whether or not the product needs to notify the customer on backorder. 
  1219. * @return bool 
  1220. */ 
  1221. public function backorders_require_notification() { 
  1222. return apply_filters( 'woocommerce_product_backorders_require_notification', ( $this->managing_stock() && 'notify' === $this->get_backorders() ), $this ); 
  1223.  
  1224. /** 
  1225. * Check if a product is on backorder. 
  1226. * @param int $qty_in_cart (default: 0) 
  1227. * @return bool 
  1228. */ 
  1229. public function is_on_backorder( $qty_in_cart = 0 ) { 
  1230. return $this->managing_stock() && $this->backorders_allowed() && ( $this->get_stock_quantity() - $qty_in_cart ) < 0 ? true : false; 
  1231.  
  1232. /** 
  1233. * Returns whether or not the product has enough stock for the order. 
  1234. * @param mixed $quantity 
  1235. * @return bool 
  1236. */ 
  1237. public function has_enough_stock( $quantity ) { 
  1238. return ! $this->managing_stock() || $this->backorders_allowed() || $this->get_stock_quantity() >= $quantity; 
  1239.  
  1240. /** 
  1241. * Returns whether or not the product has any visible attributes. 
  1242. * @return boolean 
  1243. */ 
  1244. public function has_attributes() { 
  1245. foreach ( $this->get_attributes() as $attribute ) { 
  1246. if ( $attribute->get_visible() ) { 
  1247. return true; 
  1248. return false; 
  1249.  
  1250. /** 
  1251. * Returns whether or not the product has any child product. 
  1252. * @return bool 
  1253. */ 
  1254. public function has_child() { 
  1255. return 0 < count( $this->get_children() ); 
  1256.  
  1257. /** 
  1258. * Does a child have dimensions? 
  1259. * @since 3.0.0 
  1260. * @return bool 
  1261. */ 
  1262. public function child_has_dimensions() { 
  1263. return false; 
  1264.  
  1265. /** 
  1266. * Does a child have a weight? 
  1267. * @since 3.0.0 
  1268. * @return boolean 
  1269. */ 
  1270. public function child_has_weight() { 
  1271. return false; 
  1272.  
  1273. /** 
  1274. * Check if downloadable product has a file attached. 
  1275. * @since 1.6.2 
  1276. * @param string $download_id file identifier 
  1277. * @return bool Whether downloadable product has a file attached. 
  1278. */ 
  1279. public function has_file( $download_id = '' ) { 
  1280. return $this->is_downloadable() && $this->get_file( $download_id ); 
  1281.  
  1282. /** 
  1283. * Returns whether or not the product has additonal options that need 
  1284. * selecting before adding to cart. 
  1285. * @since 3.0.0 
  1286. * @return boolean 
  1287. */ 
  1288. public function has_options() { 
  1289. return false; 
  1290.  
  1291. /** 
  1292. |-------------------------------------------------------------------------- 
  1293. | Non-CRUD Getters 
  1294. |-------------------------------------------------------------------------- 
  1295. */ 
  1296.  
  1297. /** 
  1298. * Get the product's title. For products this is the product name. 
  1299. * @return string 
  1300. */ 
  1301. public function get_title() { 
  1302. return apply_filters( 'woocommerce_product_title', $this->get_name(), $this ); 
  1303.  
  1304. /** 
  1305. * Product permalink. 
  1306. * @return string 
  1307. */ 
  1308. public function get_permalink() { 
  1309. return get_permalink( $this->get_id() ); 
  1310.  
  1311. /** 
  1312. * Returns the children IDs if applicable. Overridden by child classes. 
  1313. * @return array of IDs 
  1314. */ 
  1315. public function get_children() { 
  1316. return array(); 
  1317.  
  1318. /** 
  1319. * If the stock level comes from another product ID, this should be modified. 
  1320. * @since 3.0.0 
  1321. * @return int 
  1322. */ 
  1323. public function get_stock_managed_by_id() { 
  1324. return $this->get_id(); 
  1325.  
  1326. /** 
  1327. * Returns the price in html format. 
  1328. * @return string 
  1329. */ 
  1330. public function get_price_html( $deprecated = '' ) { 
  1331. if ( '' === $this->get_price() ) { 
  1332. $price = apply_filters( 'woocommerce_empty_price_html', '', $this ); 
  1333. } elseif ( $this->is_on_sale() ) { 
  1334. $price = wc_format_sale_price( wc_get_price_to_display( $this, array( 'price' => $this->get_regular_price() ) ), wc_get_price_to_display( $this ) ) . $this->get_price_suffix(); 
  1335. } else { 
  1336. $price = wc_price( wc_get_price_to_display( $this ) ) . $this->get_price_suffix(); 
  1337.  
  1338. return apply_filters( 'woocommerce_get_price_html', $price, $this ); 
  1339.  
  1340. /** 
  1341. * Get product name with SKU or ID. Used within admin. 
  1342. * @return string Formatted product name 
  1343. */ 
  1344. public function get_formatted_name() { 
  1345. if ( $this->get_sku() ) { 
  1346. $identifier = $this->get_sku(); 
  1347. } else { 
  1348. $identifier = '#' . $this->get_id(); 
  1349. return sprintf( '%2$s (%1$s)', $identifier, $this->get_name() ); 
  1350.  
  1351. /** 
  1352. * Get min quantity which can be purchased at once. 
  1353. * @since 3.0.0 
  1354. * @return int 
  1355. */ 
  1356. public function get_min_purchase_quantity() { 
  1357. return 1; 
  1358.  
  1359. /** 
  1360. * Get max quantity which can be purchased at once. 
  1361. * @since 3.0.0 
  1362. * @return int Quantity or -1 if unlimited. 
  1363. */ 
  1364. public function get_max_purchase_quantity() { 
  1365. return $this->is_sold_individually() ? 1 : ( $this->backorders_allowed() || ! $this->get_manage_stock() ? -1 : $this->get_stock_quantity() ); 
  1366.  
  1367. /** 
  1368. * Get the add to url used mainly in loops. 
  1369. * @return string 
  1370. */ 
  1371. public function add_to_cart_url() { 
  1372. return apply_filters( 'woocommerce_product_add_to_cart_url', $this->get_permalink(), $this ); 
  1373.  
  1374. /** 
  1375. * Get the add to cart button text for the single page. 
  1376. * @return string 
  1377. */ 
  1378. public function single_add_to_cart_text() { 
  1379. return apply_filters( 'woocommerce_product_single_add_to_cart_text', __( 'Add to cart', 'woocommerce' ), $this ); 
  1380.  
  1381. /** 
  1382. * Get the add to cart button text. 
  1383. * @return string 
  1384. */ 
  1385. public function add_to_cart_text() { 
  1386. return apply_filters( 'woocommerce_product_add_to_cart_text', __( 'Read more', 'woocommerce' ), $this ); 
  1387.  
  1388. /** 
  1389. * Returns the main product image. 
  1390. * @param string $size (default: 'shop_thumbnail') 
  1391. * @param array $attr 
  1392. * @param bool True to return $placeholder if no image is found, or false to return an empty string. 
  1393. * @return string 
  1394. */ 
  1395. public function get_image( $size = 'shop_thumbnail', $attr = array(), $placeholder = true ) { 
  1396. if ( has_post_thumbnail( $this->get_id() ) ) { 
  1397. $image = get_the_post_thumbnail( $this->get_id(), $size, $attr ); 
  1398. } elseif ( ( $parent_id = wp_get_post_parent_id( $this->get_id() ) ) && has_post_thumbnail( $parent_id ) ) { 
  1399. $image = get_the_post_thumbnail( $parent_id, $size, $attr ); 
  1400. } elseif ( $placeholder ) { 
  1401. $image = wc_placeholder_img( $size ); 
  1402. } else { 
  1403. $image = ''; 
  1404. return str_replace( array( 'https://', 'http://' ), '//', $image ); 
  1405.  
  1406. /** 
  1407. * Returns the product shipping class SLUG. 
  1408. * @return string 
  1409. */ 
  1410. public function get_shipping_class() { 
  1411. if ( $class_id = $this->get_shipping_class_id() ) { 
  1412. $term = get_term_by( 'id', $class_id, 'product_shipping_class' ); 
  1413.  
  1414. if ( $term && ! is_wp_error( $term ) ) { 
  1415. return $term->slug; 
  1416. return ''; 
  1417.  
  1418. /** 
  1419. * Returns a single product attribute as a string. 
  1420. * @param string $attribute to get. 
  1421. * @return string 
  1422. */ 
  1423. public function get_attribute( $attribute ) { 
  1424. $attributes = $this->get_attributes(); 
  1425. $attribute = sanitize_title( $attribute ); 
  1426.  
  1427. if ( isset( $attributes[ $attribute ] ) ) { 
  1428. $attribute_object = $attributes[ $attribute ]; 
  1429. } elseif ( isset( $attributes[ 'pa_' . $attribute ] ) ) { 
  1430. $attribute_object = $attributes[ 'pa_' . $attribute ]; 
  1431. } else { 
  1432. return ''; 
  1433. return $attribute_object->is_taxonomy() ? implode( ', ', wc_get_product_terms( $this->get_id(), $attribute_object->get_name(), array( 'fields' => 'names' ) ) ) : wc_implode_text_attributes( $attribute_object->get_options() ); 
  1434.  
  1435. /** 
  1436. * Get the total amount (COUNT) of ratings, or just the count for one rating e.g. number of 5 star ratings. 
  1437. * @param int $value Optional. Rating value to get the count for. By default returns the count of all rating values. 
  1438. * @return int 
  1439. */ 
  1440. public function get_rating_count( $value = null ) { 
  1441. $counts = $this->get_rating_counts(); 
  1442.  
  1443. if ( is_null( $value ) ) { 
  1444. return array_sum( $counts ); 
  1445. } elseif ( isset( $counts[ $value ] ) ) { 
  1446. return absint( $counts[ $value ] ); 
  1447. } else { 
  1448. return 0; 
  1449.  
  1450. /** 
  1451. * Get a file by $download_id. 
  1452. * @param string $download_id file identifier 
  1453. * @return array|false if not found 
  1454. */ 
  1455. public function get_file( $download_id = '' ) { 
  1456. $files = $this->get_downloads(); 
  1457.  
  1458. if ( '' === $download_id ) { 
  1459. $file = sizeof( $files ) ? current( $files ) : false; 
  1460. } elseif ( isset( $files[ $download_id ] ) ) { 
  1461. $file = $files[ $download_id ]; 
  1462. } else { 
  1463. $file = false; 
  1464.  
  1465. return apply_filters( 'woocommerce_product_file', $file, $this, $download_id ); 
  1466.  
  1467. /** 
  1468. * Get file download path identified by $download_id. 
  1469. * @param string $download_id file identifier 
  1470. * @return string 
  1471. */ 
  1472. public function get_file_download_path( $download_id ) { 
  1473. $files = $this->get_downloads(); 
  1474. $file_path = isset( $files[ $download_id ] ) ? $files[ $download_id ]->get_file() : ''; 
  1475.  
  1476. // allow overriding based on the particular file being requested 
  1477. return apply_filters( 'woocommerce_product_file_download_path', $file_path, $this, $download_id ); 
  1478.  
  1479. /** 
  1480. * Get the suffix to display after prices > 0. 
  1481. * @param string $price to calculate, left blank to just use get_price() 
  1482. * @param integer $qty passed on to get_price_including_tax() or get_price_excluding_tax() 
  1483. * @return string 
  1484. */ 
  1485. public function get_price_suffix( $price = '', $qty = 1 ) { 
  1486. $html = ''; 
  1487.  
  1488. if ( ( $suffix = get_option( 'woocommerce_price_display_suffix' ) ) && wc_tax_enabled() && 'taxable' === $this->get_tax_status() ) { 
  1489. if ( '' === $price ) { 
  1490. $price = $this->get_price(); 
  1491. $replacements = array( 
  1492. '{price_including_tax}' => wc_price( wc_get_price_including_tax( $this, array( 'qty' => $qty, 'price' => $price ) ) ),  
  1493. '{price_excluding_tax}' => wc_price( wc_get_price_excluding_tax( $this, array( 'qty' => $qty, 'price' => $price ) ) ),  
  1494. ); 
  1495. $html = str_replace( array_keys( $replacements ), array_values( $replacements ), ' <small class="woocommerce-price-suffix">' . wp_kses_post( $suffix ) . '</small>' ); 
  1496. return apply_filters( 'woocommerce_get_price_suffix', $html, $this, $price, $qty ); 
  1497.  
  1498. /** 
  1499. * Returns the availability of the product. 
  1500. * @return string[] 
  1501. */ 
  1502. public function get_availability() { 
  1503. return apply_filters( 'woocommerce_get_availability', array( 
  1504. 'availability' => $this->get_availability_text(),  
  1505. 'class' => $this->get_availability_class(),  
  1506. ), $this ); 
  1507.  
  1508. /** 
  1509. * Get availability text based on stock status. 
  1510. * @return string 
  1511. */ 
  1512. protected function get_availability_text() { 
  1513. if ( ! $this->is_in_stock() ) { 
  1514. $availability = __( 'Out of stock', 'woocommerce' ); 
  1515. } elseif ( $this->managing_stock() && $this->is_on_backorder( 1 ) ) { 
  1516. $availability = $this->backorders_require_notification() ? __( 'Available on backorder', 'woocommerce' ) : ''; 
  1517. } elseif ( $this->managing_stock() ) { 
  1518. $availability = wc_format_stock_for_display( $this ); 
  1519. } else { 
  1520. $availability = ''; 
  1521. return apply_filters( 'woocommerce_get_availability_text', $availability, $this ); 
  1522.  
  1523. /** 
  1524. * Get availability classname based on stock status. 
  1525. * @return string 
  1526. */ 
  1527. protected function get_availability_class() { 
  1528. if ( ! $this->is_in_stock() ) { 
  1529. $class = 'out-of-stock'; 
  1530. } elseif ( $this->managing_stock() && $this->is_on_backorder( 1 ) ) { 
  1531. $class = 'available-on-backorder'; 
  1532. } else { 
  1533. $class = 'in-stock'; 
  1534. return apply_filters( 'woocommerce_get_availability_class', $class, $this );