PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 11.1.0
WooCommerce v11.1.0
11.1.0 11.1.0-rc.2 11.1.0-rc.1 11.1.0-beta.2 11.1.0-beta.1 11.0.1 11.0.0 11.0.0-rc.3 11.0.0-rc.2 11.0.0-rc.1 11.0.0-beta.2 11.0.0-beta.1 10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / export / class-wc-product-csv-exporter.php
woocommerce / includes / export Last commit date
abstract-wc-csv-batch-exporter.php 2 weeks ago abstract-wc-csv-exporter.php 1 year ago class-wc-product-csv-exporter.php 2 weeks ago
class-wc-product-csv-exporter.php
803 lines
1 <?php
2 /**
3 * Handles product CSV export.
4 *
5 * @package WooCommerce\Export
6 * @version 3.1.0
7 */
8
9 use Automattic\WooCommerce\Enums\ProductStatus;
10 use Automattic\WooCommerce\Enums\ProductStockStatus;
11 use Automattic\WooCommerce\Enums\ProductType;
12 use Automattic\WooCommerce\Internal\CostOfGoodsSold\CostOfGoodsSoldController;
13 use Automattic\WooCommerce\Utilities\I18nUtil;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Include dependencies.
21 */
22 if ( ! class_exists( 'WC_CSV_Batch_Exporter', false ) ) {
23 include_once WC_ABSPATH . 'includes/export/abstract-wc-csv-batch-exporter.php';
24 }
25
26 /**
27 * WC_Product_CSV_Exporter Class.
28 */
29 class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter {
30
31 /**
32 * Type of export used in filter names.
33 *
34 * @var string
35 */
36 protected $export_type = 'product';
37
38 /**
39 * Should meta be exported?
40 *
41 * @var boolean
42 */
43 protected $enable_meta_export = false;
44
45 /**
46 * Which product types are being exported.
47 *
48 * @var array
49 */
50 protected $product_types_to_export = array();
51
52 /**
53 * Products belonging to what category should be exported.
54 *
55 * @var array
56 */
57 protected $product_category_to_export = array();
58
59 /**
60 * Specific product IDs to export, overriding other filters if hook is not used.
61 *
62 * @var array
63 */
64 protected $product_ids_to_export = array();
65
66 /**
67 * Constructor.
68 */
69 public function __construct() {
70 parent::__construct();
71 $this->set_product_types_to_export( array_keys( WC_Admin_Exporters::get_product_types() ) );
72 }
73
74 /**
75 * Should meta be exported?
76 *
77 * @param bool $enable_meta_export Should meta be exported.
78 *
79 * @since 3.1.0
80 */
81 public function enable_meta_export( $enable_meta_export ) {
82 $this->enable_meta_export = (bool) $enable_meta_export;
83 }
84
85 /**
86 * Product types to export.
87 *
88 * @param array $product_types_to_export List of types to export.
89 *
90 * @since 3.1.0
91 */
92 public function set_product_types_to_export( $product_types_to_export ) {
93 $this->product_types_to_export = array_map( 'wc_clean', $product_types_to_export );
94 }
95
96 /**
97 * Product category to export
98 *
99 * @param string $product_category_to_export Product category slug to export, empty string exports all.
100 *
101 * @since 3.5.0
102 * @return void
103 */
104 public function set_product_category_to_export( $product_category_to_export ) {
105 $this->product_category_to_export = array_map( 'sanitize_title_with_dashes', $product_category_to_export );
106 }
107
108 /**
109 * Specific product IDs to export.
110 *
111 * @param array $product_ids List of product IDs to export.
112 * @since 9.9.0
113 */
114 public function set_product_ids_to_export( $product_ids ) {
115 $this->product_ids_to_export = array_filter( array_map( 'absint', (array) $product_ids ) );
116 }
117
118 /**
119 * Return an array of columns to export.
120 *
121 * @since 3.1.0
122 * @return array
123 */
124 public function get_default_column_names() {
125 $weight_unit_label = I18nUtil::get_weight_unit_label( get_option( 'woocommerce_weight_unit', 'kg' ) );
126 $dimension_unit_label = I18nUtil::get_dimensions_unit_label( get_option( 'woocommerce_dimension_unit', 'cm' ) );
127
128 $default_columns = array(
129 'id' => __( 'ID', 'woocommerce' ),
130 'type' => __( 'Type', 'woocommerce' ),
131 'sku' => __( 'SKU', 'woocommerce' ),
132 'global_unique_id' => __( 'GTIN, UPC, EAN, or ISBN', 'woocommerce' ),
133 'name' => __( 'Name', 'woocommerce' ),
134 'published' => __( 'Published', 'woocommerce' ),
135 'featured' => __( 'Is featured?', 'woocommerce' ),
136 'catalog_visibility' => __( 'Visibility in catalog', 'woocommerce' ),
137 'short_description' => __( 'Short description', 'woocommerce' ),
138 'description' => __( 'Description', 'woocommerce' ),
139 'date_on_sale_from' => __( 'Date sale price starts', 'woocommerce' ),
140 'date_on_sale_to' => __( 'Date sale price ends', 'woocommerce' ),
141 'tax_status' => __( 'Tax status', 'woocommerce' ),
142 'tax_class' => __( 'Tax class', 'woocommerce' ),
143 'stock_status' => __( 'In stock?', 'woocommerce' ),
144 'stock' => __( 'Stock', 'woocommerce' ),
145 'low_stock_amount' => __( 'Low stock amount', 'woocommerce' ),
146 'backorders' => __( 'Backorders allowed?', 'woocommerce' ),
147 'sold_individually' => __( 'Sold individually?', 'woocommerce' ),
148 /* translators: %s: weight */
149 'weight' => sprintf( __( 'Weight (%s)', 'woocommerce' ), $weight_unit_label ),
150 /* translators: %s: length */
151 'length' => sprintf( __( 'Length (%s)', 'woocommerce' ), $dimension_unit_label ),
152 /* translators: %s: width */
153 'width' => sprintf( __( 'Width (%s)', 'woocommerce' ), $dimension_unit_label ),
154 /* translators: %s: Height */
155 'height' => sprintf( __( 'Height (%s)', 'woocommerce' ), $dimension_unit_label ),
156 'reviews_allowed' => __( 'Allow customer reviews?', 'woocommerce' ),
157 'purchase_note' => __( 'Purchase note', 'woocommerce' ),
158 'sale_price' => __( 'Sale price', 'woocommerce' ),
159 'regular_price' => __( 'Regular price', 'woocommerce' ),
160 'category_ids' => __( 'Categories', 'woocommerce' ),
161 'tag_ids' => __( 'Tags', 'woocommerce' ),
162 'shipping_class_id' => __( 'Shipping class', 'woocommerce' ),
163 'images' => __( 'Images', 'woocommerce' ),
164 'download_limit' => __( 'Download limit', 'woocommerce' ),
165 'download_expiry' => __( 'Download expiry days', 'woocommerce' ),
166 'parent_id' => __( 'Parent', 'woocommerce' ),
167 'grouped_products' => __( 'Grouped products', 'woocommerce' ),
168 'upsell_ids' => __( 'Upsells', 'woocommerce' ),
169 'cross_sell_ids' => __( 'Cross-sells', 'woocommerce' ),
170 'product_url' => __( 'External URL', 'woocommerce' ),
171 'button_text' => __( 'Button text', 'woocommerce' ),
172 'menu_order' => __( 'Position', 'woocommerce' ),
173 );
174
175 if ( wc_get_container()->get( CostOfGoodsSoldController::class )->feature_is_enabled() ) {
176 $default_columns['cogs_value'] = __( 'Cost of goods', 'woocommerce' );
177 }
178
179 return apply_filters(
180 "woocommerce_product_export_{$this->export_type}_default_columns",
181 $default_columns
182 );
183 }
184
185 /**
186 * Prepare data for export.
187 *
188 * @since 3.1.0
189 */
190 public function prepare_data_to_export() {
191 $args = array(
192 'status' => array( ProductStatus::PRIVATE, ProductStatus::PUBLISH, ProductStatus::DRAFT, ProductStatus::FUTURE, ProductStatus::PENDING ),
193 'limit' => $this->get_limit(),
194 'page' => $this->get_page(),
195 'orderby' => array(
196 'ID' => 'ASC',
197 ),
198 'return' => 'objects',
199 'paginate' => true,
200 );
201
202 // Set up query args based on whether specific IDs are being exported.
203 // We ignore type/category initially when specific IDs are provided.
204 if ( ! empty( $this->product_ids_to_export ) ) {
205 $args['include'] = $this->product_ids_to_export;
206 } else {
207 // Use the type and category filters set on the instance.
208 $args['type'] = $this->product_types_to_export;
209 if ( ! empty( $this->product_category_to_export ) ) {
210 $args['category'] = $this->product_category_to_export;
211 }
212 }
213
214 /**
215 * Filter the query args for the product export.
216 *
217 * @since 3.5.0
218 * @param array $args Arguments to pass to wc_get_products().
219 */
220 $args = apply_filters( "woocommerce_product_export_{$this->export_type}_query_args", $args );
221
222 if ( ! empty( $args['include'] ) ) {
223 $args['include'] = array_map( 'absint', (array) $args['include'] );
224 }
225
226 $products = wc_get_products( $args );
227
228 $this->total_rows = $products->total;
229 $this->row_data = array();
230 $variable_products = array();
231 $include_variations = ! isset( $args['type'] ) || in_array( ProductType::VARIATION, (array) $args['type'], true );
232
233 foreach ( $products->products as $product ) {
234 // Check if the product is variable and if either the include or category filter is active.
235 // This is to ensure that product variations are only included if they are being selectively exported or if they are part of a category.
236 if ( $include_variations &&
237 ( ! empty( $args['include'] ) || ! empty( $args['category'] ) ) &&
238 $product->is_type( ProductType::VARIABLE ) &&
239 ! in_array( $product->get_id(), $variable_products, true ) ) {
240 $variable_products[] = $product->get_id();
241 }
242
243 $this->row_data[] = $this->generate_row_data( $product );
244 }
245
246 // If variable products were identified (either through include or category filters), fetch their variations.
247 if ( ! empty( $variable_products ) ) {
248 foreach ( $variable_products as $parent_id ) {
249 $products = wc_get_products(
250 array(
251 'parent' => $parent_id,
252 'type' => array( ProductType::VARIATION ),
253 'return' => 'objects',
254 'limit' => -1,
255 )
256 );
257
258 if ( ! $products ) {
259 continue;
260 }
261
262 foreach ( $products as $product ) {
263 $this->row_data[] = $this->generate_row_data( $product );
264 }
265 }
266 }
267 }
268
269 /**
270 * Take a product and generate row data from it for export.
271 *
272 * @param WC_Product $product WC_Product object.
273 *
274 * @return array
275 */
276 protected function generate_row_data( $product ) {
277 $columns = $this->get_column_names();
278 $row = array();
279 foreach ( $columns as $column_id => $column_name ) {
280 $column_id = strstr( $column_id, ':' ) ? current( explode( ':', $column_id ) ) : $column_id;
281 $value = '';
282
283 // Skip some columns if dynamically handled later or if we're being selective.
284 if ( in_array( $column_id, array( 'downloads', 'attributes', 'meta' ), true ) || ! $this->is_column_exporting( $column_id ) ) {
285 continue;
286 }
287
288 if ( has_filter( "woocommerce_product_export_{$this->export_type}_column_{$column_id}" ) ) {
289 // Filter for 3rd parties.
290 $value = apply_filters( "woocommerce_product_export_{$this->export_type}_column_{$column_id}", '', $product, $column_id );
291
292 } elseif ( is_callable( array( $this, "get_column_value_{$column_id}" ) ) ) {
293 // Handle special columns which don't map 1:1 to product data.
294 $value = $this->{"get_column_value_{$column_id}"}( $product );
295
296 } elseif ( is_callable( array( $product, "get_{$column_id}" ) ) ) {
297 // Default and custom handling.
298 $value = $product->{"get_{$column_id}"}( 'edit' );
299 }
300
301 if ( 'description' === $column_id || 'short_description' === $column_id ) {
302 $value = $this->filter_description_field( $value );
303 }
304
305 $row[ $column_id ] = $value;
306 }
307
308 $this->prepare_downloads_for_export( $product, $row );
309 $this->prepare_attributes_for_export( $product, $row );
310 $this->prepare_meta_for_export( $product, $row );
311
312 /**
313 * Allow third-party plugins to filter the data in a single row of the exported CSV file.
314 *
315 * @since 3.1.0
316 *
317 * @param array $row An associative array with the data of a single row in the CSV file.
318 * @param WC_Product $product The product object corresponding to the current row.
319 * @param WC_Product_CSV_Exporter $exporter The instance of the CSV exporter.
320 */
321 return apply_filters( 'woocommerce_product_export_row_data', $row, $product, $this );
322 }
323
324 /**
325 * Get published value.
326 *
327 * @param WC_Product $product Product being exported.
328 *
329 * @since 3.1.0
330 * @return int
331 */
332 protected function get_column_value_published( $product ) {
333 $statuses = array(
334 ProductStatus::DRAFT => -1,
335 ProductStatus::PRIVATE => 0,
336 ProductStatus::PUBLISH => 1,
337 ProductStatus::PENDING => 2,
338 );
339
340 // Fix display for variations when parent product is a draft.
341 if ( ProductType::VARIATION === $product->get_type() ) {
342 $parent = $product->get_parent_data();
343 $status = ProductStatus::DRAFT === $parent['status'] ? $parent['status'] : $product->get_status( 'edit' );
344 } else {
345 $status = $product->get_status( 'edit' );
346 }
347
348 return isset( $statuses[ $status ] ) ? $statuses[ $status ] : -1;
349 }
350
351 /**
352 * Get formatted sale price.
353 *
354 * @param WC_Product $product Product being exported.
355 *
356 * @return string
357 */
358 protected function get_column_value_sale_price( $product ) {
359 return wc_format_localized_price( $product->get_sale_price( 'view' ) );
360 }
361
362 /**
363 * Get formatted regular price.
364 *
365 * @param WC_Product $product Product being exported.
366 *
367 * @return string
368 */
369 protected function get_column_value_regular_price( $product ) {
370 return wc_format_localized_price( $product->get_regular_price() );
371 }
372
373 /**
374 * Get product_cat value.
375 *
376 * @param WC_Product $product Product being exported.
377 *
378 * @since 3.1.0
379 * @return string
380 */
381 protected function get_column_value_category_ids( $product ) {
382 $term_ids = $product->get_category_ids( 'edit' );
383 return $this->format_term_ids( $term_ids, 'product_cat' );
384 }
385
386 /**
387 * Get product_tag value.
388 *
389 * @param WC_Product $product Product being exported.
390 *
391 * @since 3.1.0
392 * @return string
393 */
394 protected function get_column_value_tag_ids( $product ) {
395 $term_ids = $product->get_tag_ids( 'edit' );
396 return $this->format_term_ids( $term_ids, 'product_tag' );
397 }
398
399 /**
400 * Get product_shipping_class value.
401 *
402 * @param WC_Product $product Product being exported.
403 *
404 * @since 3.1.0
405 * @return string
406 */
407 protected function get_column_value_shipping_class_id( $product ) {
408 $term_ids = $product->get_shipping_class_id( 'edit' );
409 return $this->format_term_ids( $term_ids, 'product_shipping_class' );
410 }
411
412 /**
413 * Get images value.
414 *
415 * @param WC_Product $product Product being exported.
416 *
417 * @since 3.1.0
418 * @return string
419 */
420 protected function get_column_value_images( $product ) {
421 $image_ids = array_merge( array( $product->get_image_id( 'edit' ) ), $product->get_gallery_image_ids( 'edit' ) );
422 $images = array();
423
424 foreach ( $image_ids as $image_id ) {
425 $image = wp_get_attachment_image_src( $image_id, 'full' );
426
427 if ( $image ) {
428 $images[] = $image[0];
429 }
430 }
431
432 return $this->implode_values( $images );
433 }
434
435 /**
436 * Prepare linked products for export.
437 *
438 * @param int[] $linked_products Array of linked product ids.
439 *
440 * @since 3.1.0
441 * @return string
442 */
443 protected function prepare_linked_products_for_export( $linked_products ) {
444 $product_list = array();
445
446 foreach ( $linked_products as $linked_product ) {
447 if ( $linked_product->get_sku() ) {
448 $product_list[] = $linked_product->get_sku();
449 } else {
450 $product_list[] = 'id:' . $linked_product->get_id();
451 }
452 }
453
454 return $this->implode_values( $product_list );
455 }
456
457 /**
458 * Get cross_sell_ids value.
459 *
460 * @param WC_Product $product Product being exported.
461 *
462 * @since 3.1.0
463 * @return string
464 */
465 protected function get_column_value_cross_sell_ids( $product ) {
466 return $this->prepare_linked_products_for_export( array_filter( array_map( 'wc_get_product', (array) $product->get_cross_sell_ids( 'edit' ) ) ) );
467 }
468
469 /**
470 * Get upsell_ids value.
471 *
472 * @param WC_Product $product Product being exported.
473 *
474 * @since 3.1.0
475 * @return string
476 */
477 protected function get_column_value_upsell_ids( $product ) {
478 return $this->prepare_linked_products_for_export( array_filter( array_map( 'wc_get_product', (array) $product->get_upsell_ids( 'edit' ) ) ) );
479 }
480
481 /**
482 * Get parent_id value.
483 *
484 * @param WC_Product $product Product being exported.
485 *
486 * @since 3.1.0
487 * @return string
488 */
489 protected function get_column_value_parent_id( $product ) {
490 if ( $product->get_parent_id( 'edit' ) ) {
491 $parent = wc_get_product( $product->get_parent_id( 'edit' ) );
492 if ( ! $parent ) {
493 return '';
494 }
495
496 return $parent->get_sku( 'edit' ) ? $parent->get_sku( 'edit' ) : 'id:' . $parent->get_id();
497 }
498 return '';
499 }
500
501 /**
502 * Get grouped_products value.
503 *
504 * @param WC_Product $product Product being exported.
505 *
506 * @since 3.1.0
507 * @return string
508 */
509 protected function get_column_value_grouped_products( $product ) {
510 if ( ProductType::GROUPED !== $product->get_type() ) {
511 return '';
512 }
513
514 $grouped_products = array();
515 $child_ids = $product->get_children( 'edit' );
516 foreach ( $child_ids as $child_id ) {
517 $child = wc_get_product( $child_id );
518 if ( ! $child ) {
519 continue;
520 }
521
522 $grouped_products[] = $child->get_sku( 'edit' ) ? $child->get_sku( 'edit' ) : 'id:' . $child_id;
523 }
524 return $this->implode_values( $grouped_products );
525 }
526
527 /**
528 * Get download_limit value.
529 *
530 * @param WC_Product $product Product being exported.
531 *
532 * @since 3.1.0
533 * @return string
534 */
535 protected function get_column_value_download_limit( $product ) {
536 return $product->is_downloadable() && $product->get_download_limit( 'edit' ) ? $product->get_download_limit( 'edit' ) : '';
537 }
538
539 /**
540 * Get download_expiry value.
541 *
542 * @param WC_Product $product Product being exported.
543 *
544 * @since 3.1.0
545 * @return string
546 */
547 protected function get_column_value_download_expiry( $product ) {
548 return $product->is_downloadable() && $product->get_download_expiry( 'edit' ) ? $product->get_download_expiry( 'edit' ) : '';
549 }
550
551 /**
552 * Get stock value.
553 *
554 * @param WC_Product $product Product being exported.
555 *
556 * @since 3.1.0
557 * @return string
558 */
559 protected function get_column_value_stock( $product ) {
560 $manage_stock = $product->get_manage_stock( 'edit' );
561 $stock_quantity = $product->get_stock_quantity( 'edit' );
562
563 if ( $product->is_type( ProductType::VARIATION ) && 'parent' === $manage_stock ) {
564 return 'parent';
565 } elseif ( $manage_stock ) {
566 return $stock_quantity;
567 } else {
568 return '';
569 }
570 }
571
572 /**
573 * Get stock status value.
574 *
575 * @param WC_Product $product Product being exported.
576 *
577 * @since 3.1.0
578 * @return string
579 */
580 protected function get_column_value_stock_status( $product ) {
581 $status = $product->get_stock_status( 'edit' );
582
583 if ( ProductStockStatus::ON_BACKORDER === $status ) {
584 return 'backorder';
585 }
586
587 return ProductStockStatus::IN_STOCK === $status ? 1 : 0;
588 }
589
590 /**
591 * Get backorders.
592 *
593 * @param WC_Product $product Product being exported.
594 *
595 * @since 3.1.0
596 * @return string
597 */
598 protected function get_column_value_backorders( $product ) {
599 $backorders = $product->get_backorders( 'edit' );
600
601 switch ( $backorders ) {
602 case 'notify':
603 return 'notify';
604 default:
605 return wc_string_to_bool( $backorders ) ? 1 : 0;
606 }
607 }
608
609 /**
610 * Get low stock amount value.
611 *
612 * @param WC_Product $product Product being exported.
613 *
614 * @since 3.5.0
615 * @return int|string Empty string if value not set
616 */
617 protected function get_column_value_low_stock_amount( $product ) {
618 return $product->managing_stock() && $product->get_low_stock_amount( 'edit' ) ? $product->get_low_stock_amount( 'edit' ) : '';
619 }
620
621 /**
622 * Get type value.
623 *
624 * @param WC_Product $product Product being exported.
625 *
626 * @since 3.1.0
627 * @return string
628 */
629 protected function get_column_value_type( $product ) {
630 $types = array();
631 $types[] = $product->get_type();
632
633 if ( $product->is_downloadable() ) {
634 $types[] = 'downloadable';
635 }
636
637 if ( $product->is_virtual() ) {
638 $types[] = 'virtual';
639 }
640
641 return $this->implode_values( $types );
642 }
643
644 /**
645 * Filter description field for export.
646 * Convert newlines to '\n'.
647 *
648 * @param string $description Product description text to filter.
649 *
650 * @since 3.5.4
651 * @return string
652 */
653 protected function filter_description_field( $description ) {
654 $description = str_replace( '\n', "\\\\n", $description );
655 $description = str_replace( "\n", '\n', $description );
656 return $description;
657 }
658 /**
659 * Export downloads.
660 *
661 * @param WC_Product $product Product being exported.
662 * @param array $row Row being exported.
663 *
664 * @since 3.1.0
665 */
666 protected function prepare_downloads_for_export( $product, &$row ) {
667 if ( $product->is_downloadable() && $this->is_column_exporting( 'downloads' ) ) {
668 $downloads = $product->get_downloads( 'edit' );
669
670 if ( $downloads ) {
671 $i = 1;
672 foreach ( $downloads as $download ) {
673 /* translators: %s: download number */
674 $this->column_names[ 'downloads:id' . $i ] = sprintf( __( 'Download %d ID', 'woocommerce' ), $i );
675 /* translators: %s: download number */
676 $this->column_names[ 'downloads:name' . $i ] = sprintf( __( 'Download %d name', 'woocommerce' ), $i );
677 /* translators: %s: download number */
678 $this->column_names[ 'downloads:url' . $i ] = sprintf( __( 'Download %d URL', 'woocommerce' ), $i );
679 $row[ 'downloads:id' . $i ] = $download->get_id();
680 $row[ 'downloads:name' . $i ] = $download->get_name();
681 $row[ 'downloads:url' . $i ] = $download->get_file();
682 ++$i;
683 }
684 }
685 }
686 }
687
688 /**
689 * Export attributes data.
690 *
691 * @param WC_Product $product Product being exported.
692 * @param array $row Row being exported.
693 *
694 * @since 3.1.0
695 */
696 protected function prepare_attributes_for_export( $product, &$row ) {
697 if ( $this->is_column_exporting( 'attributes' ) ) {
698 $attributes = $product->get_attributes();
699 $default_attributes = $product->get_default_attributes();
700
701 if ( count( $attributes ) ) {
702 $i = 1;
703 foreach ( $attributes as $attribute_name => $attribute ) {
704 /* translators: %s: attribute number */
705 $this->column_names[ 'attributes:name' . $i ] = sprintf( __( 'Attribute %d name', 'woocommerce' ), $i );
706 /* translators: %s: attribute number */
707 $this->column_names[ 'attributes:value' . $i ] = sprintf( __( 'Attribute %d value(s)', 'woocommerce' ), $i );
708 /* translators: %s: attribute number */
709 $this->column_names[ 'attributes:visible' . $i ] = sprintf( __( 'Attribute %d visible', 'woocommerce' ), $i );
710 /* translators: %s: attribute number */
711 $this->column_names[ 'attributes:taxonomy' . $i ] = sprintf( __( 'Attribute %d global', 'woocommerce' ), $i );
712
713 if ( is_a( $attribute, 'WC_Product_Attribute' ) ) {
714 $row[ 'attributes:name' . $i ] = html_entity_decode( wc_attribute_label( $attribute->get_name(), $product ), ENT_QUOTES );
715
716 if ( $attribute->is_taxonomy() ) {
717 $terms = $attribute->get_terms();
718 $values = array();
719
720 foreach ( $terms as $term ) {
721 $values[] = $term->name;
722 }
723
724 $row[ 'attributes:value' . $i ] = $this->implode_values( $values );
725 $row[ 'attributes:taxonomy' . $i ] = 1;
726 } else {
727 $row[ 'attributes:value' . $i ] = $this->implode_values( $attribute->get_options() );
728 $row[ 'attributes:taxonomy' . $i ] = 0;
729 }
730
731 $row[ 'attributes:visible' . $i ] = $attribute->get_visible();
732 } else {
733 $row[ 'attributes:name' . $i ] = html_entity_decode( wc_attribute_label( $attribute_name, $product ), ENT_QUOTES );
734
735 if ( 0 === strpos( $attribute_name, 'pa_' ) ) {
736 $option_term = get_term_by( 'slug', $attribute, $attribute_name ); // @codingStandardsIgnoreLine.
737 $row[ 'attributes:value' . $i ] = $option_term && ! is_wp_error( $option_term ) ? html_entity_decode( str_replace( ',', '\\,', $option_term->name ), ENT_QUOTES ) : html_entity_decode( str_replace( ',', '\\,', $attribute ), ENT_QUOTES );
738 $row[ 'attributes:taxonomy' . $i ] = 1;
739 } else {
740 $row[ 'attributes:value' . $i ] = html_entity_decode( str_replace( ',', '\\,', $attribute ), ENT_QUOTES );
741 $row[ 'attributes:taxonomy' . $i ] = 0;
742 }
743
744 $row[ 'attributes:visible' . $i ] = '';
745 }
746
747 if ( $product->is_type( ProductType::VARIABLE ) && isset( $default_attributes[ sanitize_title( $attribute_name ) ] ) ) {
748 /* translators: %s: attribute number */
749 $this->column_names[ 'attributes:default' . $i ] = sprintf( __( 'Attribute %d default', 'woocommerce' ), $i );
750 $default_value = $default_attributes[ sanitize_title( $attribute_name ) ];
751
752 if ( 0 === strpos( $attribute_name, 'pa_' ) ) {
753 $option_term = get_term_by( 'slug', $default_value, $attribute_name ); // @codingStandardsIgnoreLine.
754 $row[ 'attributes:default' . $i ] = $option_term && ! is_wp_error( $option_term ) ? $option_term->name : $default_value;
755 } else {
756 $row[ 'attributes:default' . $i ] = $default_value;
757 }
758 }
759 ++$i;
760 }
761 }
762 }
763 }
764
765 /**
766 * Export meta data.
767 *
768 * @param WC_Product $product Product being exported.
769 * @param array $row Row data.
770 *
771 * @since 3.1.0
772 */
773 protected function prepare_meta_for_export( $product, &$row ) {
774 if ( $this->enable_meta_export ) {
775 $meta_data = $product->get_meta_data();
776
777 if ( count( $meta_data ) ) {
778 $meta_keys_to_skip = apply_filters( 'woocommerce_product_export_skip_meta_keys', array(), $product );
779
780 $i = 1;
781 foreach ( $meta_data as $meta ) {
782 if ( in_array( $meta->key, $meta_keys_to_skip, true ) ) {
783 continue;
784 }
785
786 // Allow 3rd parties to process the meta, e.g. to transform non-scalar values to scalar.
787 $meta_value = apply_filters( 'woocommerce_product_export_meta_value', $meta->value, $meta, $product, $row );
788
789 if ( ! is_scalar( $meta_value ) ) {
790 continue;
791 }
792
793 $column_key = 'meta:' . esc_attr( $meta->key );
794 /* translators: %s: meta data name */
795 $this->column_names[ $column_key ] = sprintf( __( 'Meta: %s', 'woocommerce' ), $meta->key );
796 $row[ $column_key ] = $meta_value;
797 ++$i;
798 }
799 }
800 }
801 }
802 }
803