Créer un plug-in d’ export WooCommerce Booking

Si vous ne connaissez pas l’add-on WooCommerce Booking, c’est une extension qui s’ajoute à WooCommerce et qui permet de créer des produits reservables (événements, hôtels, tout ce que vous pouvez imaginer).

J’ai utilisé il y a quelques temps cette extension pour un projet de vente en ligne de billets pour des événements, avec différents intervenants, différentes dates et horaires reservables.

Pour plus de facilité et gagner du temps, mon client à voulu un outil d’export de toutes ses réservations, vers un fichier CSV.

Il existe apparemment quelques extensions qui répondent déjà à ce besoin, mais pourquoi ne pas développer notre propre exporteur grâce à un mu-plugin ?

Pour créer un plug-in d’ export WooCommerce Booking, déclarons notre mu-plugin ainsi que notre Class :

<?php 
/**
 * @package MC_Export_Bookings_CV_to_CSV
 * @version 1.0.0
 */
/*
Plugin Name: MC Export Bookings WC to CSV
*/
/**
 * Main plugin class
 *
 * @since 0.1
 **/
class MC_Export_Bookings {
	
	/**
	 * Class contructor
	 *
	 * @since 0.1
	 **/
	public function __construct() {
		add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
		add_action( 'admin_init', array( $this, 'generate_csv' ) );
	}

Dans notre fonction construct nous ajoutons deux actions:

La première est ajoutée au hook admin_menu avec la fonction add_admin_pages – qui  permet d’ajouter notre page d’administration.
La seconde est ajoutée au hook admin_init avec la fonction generate_csv – qui générera le fichier XML.

La page d’administration de notre plug-in d’ export WooCommerce Booking

Construisons donc cette page d’administration qui permettra de sélectionner le produit dont nous souhaitons exporter les réservations :

/**
	 * Add administration menus
	 *
	 * @since 0.1
	 **/
	public function add_admin_pages() {
		add_submenu_page( 'edit.php?post_type=wc_booking', __( 'Exporter réservations', 'export-bookings-to-csv' ), __( 'Exporter réservations', 'export-bookings-to-csv' ), 'manage_options', 'export-bookings-to-csv', array( $this,'export_bookings_to_csv') );
	}

Je vous invite à lire la doc sur la fonction add_submenu_page, mais dans l’ordre nous précisons :

La page parent (puisque nous ajoutons un submenu),

Notre titre de page

Notre titre de menu

La capacité utilisateur requise pour accéder à cette fonctionnalité

Le slug du menu

Et enfin la fonction de callback que nous souhaitons afficher dans la page d’administration, ici export_bookings_to_csv :

/**
	 * Process content of CSV file
	 *
	 * @since 0.1
	 **/
	 public function export_bookings_to_csv(){
		echo '<h1>Exporter les réservations</h1>';
		
		global $wpdb;
		
		$args = array(
			    'post_type' => 'product',
			    'posts_per_page' => -1,  
		);
		$products = get_posts($args);
		// Query all products for display them in the select in the backoffice
	?>
		<div class="wrap">
			<h2>Exporter les réservations</h2>
			<form method="post" name="csv_exporter_form" action="" enctype="multipart/form-data">
				<?php wp_nonce_field( 'export-bookings-bookings_export', '_wpnonce-export-bookings-bookings_export' ); ?>
				<p><h3>Choisissez quel type d'évènement vous souhaitez exporter:</h3></p>
				
				<label>Evènement:</label>
				<select name="resource" id="resource">
					<option value="">Selectionner un évènement</option>
					<?php foreach($products as $product) {?>
						<option value="<?php echo  $product->ID;?>" name="event"><?php echo  $product->post_title; ?></option>
					<?php }?>
				</select>
				
				<h3>Cliquez pour sauvegardez l'export. Si vous faites plusieurs exports, renommez-les en fonction.</h3>
				
				<p class="submit"><input type="submit" name="Submit" value="Exporter" /></p>
			</form>
		</div>
		<?php 
	}

Rien de particulier ici, nous faisons une query sur les produits WooCommerce afin de les afficher sous forme de select en back-office.

Ligne 28 on place les IDs des produits dans la « value » et le nom du produit dans le contenu.

Construction des données à exporter

Lorsqu’un export est demandé :

public function generate_csv(){
		if ( isset( $_POST['_wpnonce-export-bookings-bookings_export'] ) ) {
			global $wpdb;
			$event_name = $_POST['resource']; // the value selected in the dropdown in back office = product id
			
			$args = array(
			    'post_type' => 'shop_order',
 				'post_status' => 'wc-completed',
			    'posts_per_page' => -1,
			   
			);
			$orders = get_posts($args);
			// Query all orders which are completed
			foreach($orders as $o):
			    $order_id = $o->ID;
			    $order = new WC_Order($order_id);
			
			    foreach( $order->get_items() as $item ):
			    $event_id = $item['product_id']; // product_id = meta_key for the product id attached to the booking in the woocommerce_order_itemmeta table
				$product_id = $item['Booking ID']; // Booking id = meta_key for the booking id in the woocommerce_order_itemmeta table
				if($event_id == $event_name && !empty($product_id)): // check if the selected product in the back office is equal to product_id in database AND product_id not empty
			    	
			    	$product = $item['name']; // product name
			    	/* here we are querying informations in the postmeta table */
			    	$ressource_id = get_post_meta($product_id, '_booking_resource_id', true); // get the resource id. if you're not using resources remove this
			    	$booking_ressource = get_the_title($ressource_id); // get the resource name
					$start_date_long = get_post_meta( $product_id, '_booking_start', true ); 
					$start_date_timestamp = DateTime::createFromFormat('YmdHis', $start_date_long);
					$start_date = $start_date_timestamp->format('d-m-Y h:i');
					$end_date_long = get_post_meta( $product_id, '_booking_end', true );
					$end_date_timestamp = DateTime::createFromFormat('YmdHis', $end_date_long);
					$end_date = $end_date_timestamp->format('d-m-Y h:i');
					$customer_name = get_post_meta( $order_id, '_billing_first_name', true );
					$customer_last_name = get_post_meta( $order_id, '_billing_last_name', true );
					$customer_mail = get_post_meta( $order_id, '_billing_email', true);
					$customer_phone = get_post_meta( $order_id, '_billing_phone', true);
					$price = get_post_meta($order_id, '_order_total', true);
			    	if($start_date && $end_date){ // check if there are a start date and end date
						$data[] = array($product_id, $product, $start_date, $end_date, $booking_ressource, $customer_name, $customer_last_name, $customer_mail, $customer_phone, $price);
						// here we construct the array to pass informations to export CSV
					}
					endif;
			   endforeach;
			endforeach;	
			
			$this->array_to_csv_download($data); // pass $data to array_to_csv_download function
			exit;
		}
	}

A la ligne 4, on récupère le produit sélectionné en back-office via le sélecteur.

Ligne 7,8 on fait une Query sur toutes les commandes passées et en statut complétée (On ne veut pas exporter de commandes abandonnées, etc.)

A la ligne 16 on instancie un nouvel object WC_Order pour chaque commande, ce qui nous permet de boucler sur chaque produit commandé et vérifier en ligne 21 que le produit sélectionné (ligne 4) se trouve en base.

En ligne 25 on récupère les metas relatives à la réservation, ici j’ai eu besoin de récupérer les dates de réservations, le nom, prénom, e-mail et téléphone du client ainsi que le prix payé. Supprimez ce qui vous n’est pas utile et ajoutez ce qu’il vous manque 🙂

A la ligne 28 nous créons un format de date lisible grace à la méthode DateTime::createFromFormat d’après le format timestamp stocké par WooCommerce.

Une vérification s’impose en ligne 38 : avons-nous bien une date de début et une date de fin pour cette réservation ? Si oui, nous construisons notre tableau $data[] avec toutes les données collectées précédemment.

Enfin, en ligne 46 on appelle la fonction array_to_csv_download avec pour argument notre tableau $data.

Ecrire notre fichier CSV

function array_to_csv_download($data, $filename = "export.csv", $delimiter=",") {
		// echo 'here';
		ob_start();
		// open raw memory as file so no temp files needed, you might run out of memory though
		$f = fopen('php://output', 'w'); 
		$header = array('No Resas', 'Evenenements', 'Debut', 'Fin', 'Ressource', 'Nom', 'Prenom', 'Mail', 'Telephone', 'Prix paye');
		fputcsv($f, $header, ';');
		// loop over the input array
		foreach ($data as $line) { 
			// generate csv lines from the inner arrays
			fputcsv($f, $line, ';'); 
		}
		fclose($f);
		// rewrind the "file" with the csv lines
		// fseek($f, 0);
		header("Content-Type: application/csv");    
		header("Content-Disposition: attachment; filename=".$filename);  
		// Disable caching
		header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1
		header("Pragma: no-cache"); // HTTP 1.0
		header("Expires: 0"); // Proxies
	}
}
new MC_Export_Bookings;

En ligne 5 on crée un nouveau fichier

En ligne 6 on construit nos colonnes, une pour chaque donnée.

En ligne 7 on formate puis écrit ces colonnes dans notre fichier

En ligne 9 on boucle sur chaque donnée de notre tableau $data puis en ligne 11 on écrit dans notre fichier.

En ligne 13 on referme ce fichier.

A partir de la ligne 16 ce sont des paramètres de type header, relatifs

au fichier en lui même, je vous invite à lire la doc relative.

 

Et voilà !

Vous pouvez retrouver l’extension complète ici 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nom *

e666131114b400a2a91f3636039c410a7777777777777777777777777777777