Skip to content

Instantly share code, notes, and snippets.

@Langmans
Created June 10, 2015 08:46
Show Gist options
  • Save Langmans/9e9dc43ec60cc928813c to your computer and use it in GitHub Desktop.
Save Langmans/9e9dc43ec60cc928813c to your computer and use it in GitHub Desktop.
woocommerce product variation importer - two columns required: post_parent and sku.
<?php
if ( $_SERVER['HTTP_HOST'] != 'localhost' ) {
die( 'Only locally enabled! change import-csv.php.' );
}
$csv = filter_input( INPUT_GET, 'csv' );
if ( ! $csv ) {
?>
<form>
<p>
<label>
<select name="csv" required>
CSV file
<option value="" disabled>Kies</option>
<?php
if ( $csv_files = glob( 'csv/*.csv' ) ) {
foreach ( $csv_files as $file ) {
echo '<option>', $file, '</option>';
}
}?>
</select>
</label>
</p>
<button>Import variations</button>
</form>
<?php
die;
}
if ( $fh = fopen( $csv, 'r' ) ) {
include 'wp-load.php';
set_time_limit( 0 );
error_reporting( - 1 );
ini_set( 'display_errors', 'On' );
$columns = null;
while ( ob_get_level() ) {
ob_end_flush();
}
ob_implicit_flush( true );
//http://woothemes.github.io/woocommerce-rest-api-docs/#products-properties
$editable_meta = array(
//If the variation is downloadable or not. Downloadable variations give access to a file upon purchase
'downloadable' => 'boolean',
//If the variation is virtual or not. Virtual variations are intangible and aren’t shipped
'virtual' => 'boolean',
//SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased
'sku' => 'string',
//Variation regular price
'regular_price' => 'float',
//Variation sale price
'sale_price' => 'float',
//Sets the sale start date. Date in the YYYY-MM-DD format WRITE-ONLY
'sale_price_dates_from' => 'float',
//Sets the sale end date. Date in the YYYY-MM-DD format WRITE-ONLY
'sale_price_dates_to' => 'float',
//Tax status. The options are: taxable, shipping (Shipping only) and none
'tax_status' => 'string',
//Tax class
'tax_class' => 'string',
//Enable stock management at variation level
'managing_stock' => 'boolean',
//Stock quantity. If is a variable variation this value will be used to control stock for all variations, unless you define stock at variation level.
'stock_quantity' => 'integer',
//Controls whether or not the variation is listed as “in stock” or “out of stock” on the frontend.
'in_stock' => 'boolean',
//Variation weight in decimal format
'weight' => 'string',
//List of the variation dimensions. See Dimensions Properties
'dimensions' => 'array',
//Shipping class slug. Shipping classes are used by certain shipping methods to group similar products
'shipping_class' => 'string',
//Variation featured image. See Images Properties
'images' => 'array',
//List of variation attributes. Similar to a simple or variable product, but for variation indicate the attributes used to form the variation. See Attributes Properties
'attributes' => 'array',
//List of downloadable files. See Downloads Properties
'downloads' => 'array',
//Amount of times the variation can be downloaded. In write-mode you can sent a blank string for unlimited re-downloads. e.g ''
'download_limit' => 'integer',
//Number of days that the customer has up to be able to download the varition. In write-mode you can sent a blank string for never expiry. e.g ''
'download_expiry' => 'integer',
);
$str2number = function ( $str ) {
$number_unformat = function ( $number, $force_number = true, $dec_point = '.', $thousands_sep = ',' ) {
if ( $force_number ) {
$number = preg_replace( '/^[^\d]+/', '', $number );
} else if ( preg_match( '/^[^\d]+/', $number ) ) {
return false;
}
$type = ( strpos( $number, $dec_point ) === false ) ? 'int' : 'float';
$number = str_replace( array( $dec_point, $thousands_sep ), array( '.', '' ), $number );
settype( $number, $type );
return $number;
};
// 0 -9, . and ,
$str = preg_replace( '@[^\d,\.]+@', '', $str );
$point_pos = strpos( $str, '.' );
$comma_pos = strpos( $str, ',' );
// both comma and point found, and comma is later then point (comma as decimal seperator);
if ( $point_pos && $comma_pos ) {
return $number_unformat( $str,
true,
$point_pos > $comma_pos ? '.' : ',',
$point_pos > $comma_pos ? ',' : '.'
);
} elseif ( $point_pos ) {
return $number_unformat( $str, true, '.', '' );
} else {
return $number_unformat( $str, true, ',', '' );
}
};
while ( $values = fgetcsv( $fh, 1024 * 8, ';' ) ) {
sleep( 1 );
if ( ! $columns ) {
$columns = $values;
if ( ! in_array( 'post_parent', $columns ) ) {
die( 'there is no post_parent column in that csv file.' );
}
if ( ! in_array( 'sku', $columns ) ) {
die( 'there is no sku column in that csv file.' );
}
continue;
}
// convert the csv to assoc array.
$row = array();
foreach ( $columns as $i => $column ) {
$row[ $column ] = $values[ $i ];
}
echo '<hr>'/*, json_encode( $row ), '<br>'*/
;
/** @var $parent_product WC_Product_Variable */
/** @var $product WC_Product_Variation */
// find the product by sku.
if ( ! ( $product = wc_get_product( wc_get_product_id_by_sku( $row['sku'] ) ) ) ) {
$parent_product = wc_get_product( $row['post_parent'] );
if ( ! $parent_product ) {
echo 'Parent product not found!<br>';
continue;
}
/** @var WP_Post $parent_post */
$parent_post = $parent_product->post;
$variation_post_id = wp_insert_post( array(
'post_author' => $parent_post->post_author,
'post_parent' => $row['post_parent'],
'post_type' => 'product_variation',
'post_status' => 'publish',
'ping_status' => 'open',
'comment_status' => 'open'
) );
update_post_meta( $variation_post_id, '_sku', $row['sku'] );
echo 'Adding variation: ', $variation_post_id, json_encode( $row ), '<br>';
$product = wc_get_product( $variation_post_id );
} else {
// var_dump($product);
echo 'Updating variation: ', $product->variation_id, json_encode( $row ), '<br>';
}
echo 'Title: ', json_encode( $product->get_title() ), '<br>';
foreach ( $editable_meta as $meta_key => $meta_type ) {
if ( in_array( $meta_key, $columns ) ) {
// it's set in the csv.
// convert the value.
$new_value = $row[ $meta_key ];
// arrays are a little weird.
if ( $meta_type == 'array' ) {
// parse_str( $new_value, $new_value );
continue;
} else {
if ( $meta_type == 'float' || $meta_type == 'integer' ) {
$new_value = trim( $new_value );
if ( $new_value !== '' ) {
$new_value = $str2number( $new_value );
}
} else {
settype( $new_value, $meta_type );
}
}
echo 'Setting meta:', json_encode( compact( 'meta_key', 'new_value' ) ), '<br>';
update_post_meta( $product->variation_id, '_' . $meta_key, $new_value );
} else {
echo 'Meta not found:', $meta_key, '(', $meta_type, ')<br>';
}
}
foreach ( $product->get_attributes() as $attribute_slug => $attribute ) {
$options = preg_split( '@\s*|\s*@', $attribute['value'] );
$slug = 'attribute_' . $attribute_slug;
if ( isset( $row[ $slug ] ) ) {
$val = $row[ $slug ];
echo 'Setting attribute:', json_encode( compact( 'slug', 'val' ) ), '<br>';
update_post_meta( $product->variation_id, $slug, $val );
} else {
echo 'Attribute not found in csv: ', $attribute_slug, '<br>';
}
}
// wc_delete_product_transients( $row['post_parent'] );
// wc_delete_product_transients( $product->variation_id );
//
// WC_Product_Variable::sync( $row['post_parent'] );
// WC_Product_Variable::sync( $product->variation_id );
}
fclose( $fh );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment