Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Process WooCommerce products and set correct downloadable files if they've been offloaded by WP Offload Media
<?php
namespace Mosaika;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Register our custom commands.
* * Usage:
* * Dry run: wp as3cf update_products_downloadable_files
* * Real run: wp as3cf update_products_downloadable_files --dry-run=0
*/
if ( class_exists( 'WP_CLI' ) ) {
\WP_CLI::add_command( 'as3cf', 'Mosaika\Commands' );
}
class Commands {
/**
* Update WooCommerce products downloadable files to benefit from WP Offload Media features.
* Products downloadable files will be linked to their offloaded version,
* and this offloaded media will be set as private.
*
* @param array $args
* @param array $assoc_args
* @return void
*/
public function update_products_downloadable_files( $args, $assoc_args ) {
$defaults = [
'dry-run' => true,
'batch-size' => 100,
];
$this->args = wp_parse_args( $assoc_args, $defaults );
$dry_run = (bool) $this->args['dry-run'];
$batch_size = (int) $this->args['batch-size'];
$query_args = [
'downloadable' => 'true',
'status' => [ 'draft', 'pending', 'private', 'publish' ],
'return' => 'ids',
'limit' => 9999,
];
$products = new \WC_Product_Query( $query_args );
$total_products = count( $products->get_products() );
$num_batches = ceil( $total_products / $batch_size );
$products_processed = 0;
$downloads_processed = 0;
if ( empty( $products->get_products() ) ) {
\WP_CLI::line( 'No products found, stopping here.' );
return;
}
if ( $dry_run ) {
$intro = sprintf( 'Fake-processing %1$d products: link to S3 media and turn private.', $total_products );
} else {
$intro = sprintf( 'Processing %1$d products: link to S3 media and turn private.', $total_products );
}
$progress = \WP_CLI\Utils\make_progress_bar( $intro, $num_batches );
\WP_CLI::line( '=============================================================================' );
\WP_CLI::line( sprintf(
'Going through %1$d products: now analyzing %2$d batches of %3$d items.',
$total_products,
$num_batches,
$batch_size
) );
\WP_CLI::line( '=============================================================================' );
for ( $j = 0; $j < $num_batches; $j++ ) {
\WP_CLI::line( sprintf( 'Starting batch #%1$d / %2$d.', $j, $num_batches ) );
$offset = $j * $batch_size;
$query_args['offset'] = $offset;
$products = new \WC_Product_Query( $query_args );
foreach ( $products->get_products() as $product_id ) {
$product = wc_get_product( $product_id );
$downloads = $product->get_downloads( 'edit' );
$new_downloads = [];
foreach ( $downloads as $k => $download ) {
$media_id = attachment_url_to_postid( $download->get_file() );
$s3_info = ( (int) $media_id > 0 ) ? get_post_meta( (int) $media_id, 'amazonS3_info', true ) : null;
// Can't find media, or we do not have any S3 data: keep downloadable file as it is.
if ( (int) $media_id === 0 || empty( $s3_info ) || ! is_array( $s3_info ) || ! isset( $s3_info['provider'] ) || $s3_info['provider'] !== 'aws' ) {
$new_downloads[ $k ] = $download;
continue;
}
$s3_shortcode = sprintf( '[amazon_s3 id="%1$d"]', (int) $media_id );
$new_key = wp_generate_uuid4();
$download->set_file( $s3_shortcode );
$download->set_id( $new_key );
$new_downloads[ $new_key ] = $download;
$downloads_processed++;
}
if ( ! empty( $new_downloads ) && ! $dry_run ) {
$product->set_downloads( $new_downloads );
$product->save();
}
$products_processed++;
}
$progress->tick();
}
$progress->finish();
\WP_CLI::line( "- {$products_processed} products were processed: {$downloads_processed} downloadable files were updated." );
}
}
@psaikali

This comment has been minimized.

Copy link
Owner Author

commented May 21, 2019

⚠️ On L101, a new download ID is generated (otherwise, the ->save() method just does nothing).
Note that it's a messy hack because previous downloads permissions depend on this ID.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.