PageRenderTime 57ms CodeModel.GetById 12ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 1ms

/wp-content/plugins/woocommerce-api-manager/classes/class-wc-api-helpers.php

https://github.com/Acekid88/website
PHP | 1463 lines | 750 code | 333 blank | 380 comment | 179 complexity | f6b313ca12df34430fe2535b82e64cc4 MD5 | raw file
   1<?php
   2
   3// Exit if accessed directly
   4if ( ! defined( 'ABSPATH' ) ) exit;
   5
   6/**
   7 * WooCommerce API Manager Helpers Class
   8 *
   9 * @package Update API Manager/Helpers
  10 * @author Todd Lahman LLC
  11 * @copyright   Copyright (c) 2011-2013, Todd Lahman LLC
  12 * @since 1.0.0
  13 *
  14 */
  15
  16class WC_Api_Manager_Helpers {
  17
  18	public static $user_meta_key_orders 		= 'wc_am_orders';
  19	public static $user_meta_key_activations 	= 'wc_am_activations_';
  20
  21	// For troubleshooting
  22	//exit( var_dump( $wpdb->last_query ) );
  23
  24	/**
  25	 * order_complete function.
  26	 *
  27	 * Order is complete - update activation_limit if Software Add-on activated, and saves user_meta data
  28	 *
  29	 * Updates the number of activations per license key according to the API Manager settings
  30	 * Saves array of data for each order generated for a customer
  31	 *
  32	 */
  33	public static function order_complete( $order_id ) {
  34		global $wpdb;
  35
  36		$order = new WC_Order( $order_id );
  37
  38		if ( count( $order->get_items() ) > 0 ) {
  39
  40			foreach ( $order->get_items() as $item ) {
  41
  42				$item_product_id = ( isset( $item['product_id'] ) ) ? $item['product_id'] : $item['id'];
  43
  44				$item_variation_id = ( isset( $item['variation_id'] ) ) ? $item['variation_id'] : $item['id'];
  45
  46				// verify this is a variable product
  47				if ( $item_variation_id > 0 ) {
  48
  49					$meta = get_post_custom( $item_product_id );
  50
  51					$meta_var = get_post_custom( $item_variation_id );
  52
  53					if ( $meta['_downloadable'][0] == 'yes' || $meta_var['_downloadable'][0] == 'yes' ) {
  54
  55						$quantity = isset( $item['item_meta']['_qty'][0] ) ? absint( $item['item_meta']['_qty'][0] ) : 1;
  56
  57						/**
  58						 * If the parent product has a tile else use the variable product title
  59						 */
  60						if ( isset( $meta_var['_api_software_title_parent'][0] ) && $meta_var['_api_software_title_parent'][0] != '' && ! empty( $meta_var['_api_software_title_parent'][0] ) ) {
  61
  62							$software_title_parent = $meta_var['_api_software_title_parent'][0];
  63							$software_title = $meta_var['_api_software_title_parent'][0];
  64
  65						} else if ( isset( $meta_var['_api_software_title_var'][0] ) && $meta_var['_api_software_title_var'][0] != '' && ! empty( $meta_var['_api_software_title_var'][0] ) ) {
  66
  67							$software_title_var = $meta_var['_api_software_title_var'][0];
  68							$software_title = $meta_var['_api_software_title_var'][0];
  69
  70						} else {
  71
  72							$software_title = '';
  73						}
  74
  75						if ( get_option( 'wc_api_manager_software_add_on_license_key' ) == 'yes' && self::is_plugin_active( 'woocommerce-software-add-on/woocommerce-software.php' ) ) {
  76							// Get the order_id
  77							$lic_order_id = $wpdb->get_var( $wpdb->prepare( "
  78								SELECT order_id FROM {$wpdb->prefix}woocommerce_software_licences
  79								WHERE order_id = %d
  80								LIMIT 1
  81							", $order_id ) );
  82
  83							// verify the license has been created before continuing
  84							if ( $lic_order_id ) {
  85
  86								for ( $i = 0; $i < $quantity; $i++ ) {
  87
  88					                $data = array(
  89										'order_id' 				=> $order_id,
  90										'activations_limit'		=> empty( $meta_var['_api_activations'][0] ) ? '' : (int) $meta_var['_api_activations'][0],
  91										'software_title' 		=> empty( $software_title ) ? '' : (string) $software_title,
  92										'current_version'		=> empty( $meta_var['_api_new_version'][0] ) ? '' : (string) $meta_var['_api_new_version'][0],
  93							        );
  94
  95									self::update_licence_key( $data );
  96
  97									// Saves meta data for this order to be used by the API Manager if Software Add-on license is required
  98					                $meta_data =
  99					                		array( $order->order_key =>
 100					                			array(
 101								                	'user_id'						=> $order->user_id,
 102													'order_id' 						=> $order_id,
 103													'order_key' 					=> $order->order_key,
 104													'license_email' 				=> $order->billing_email,
 105													'_api_software_title_parent' 	=> empty( $software_title_parent ) ? '' : (string) $software_title_parent,
 106													'_api_software_title_var' 		=> empty( $software_title_var ) ? '' : (string) $software_title_var,
 107													'software_title' 				=> empty( $software_title ) ? '' : (string) $software_title,
 108													'parent_product_id'				=> empty( $item_product_id ) ? '' : (int) $item_product_id,
 109													'variable_product_id'			=> empty( $item_variation_id ) ? '' : (int) $item_variation_id,
 110													'current_version'				=> empty( $meta_var['_api_new_version'][0] ) ? '' : (string) $meta_var['_api_new_version'][0],
 111													'_api_activations'				=> empty( $meta_var['_api_activations'][0] ) ? '' : (int) $meta_var['_api_activations'][0],
 112													'_api_activations_parent'		=> '',
 113													'_api_update_permission'		=> 'yes',
 114													'is_variable_product'			=> 'yes',
 115													'license_type'					=> '',
 116													'expires'						=> '',
 117													)
 118					                			);
 119
 120									self::save_order_complete_user_meta( $meta_data, $order->order_key );
 121
 122								}
 123							}
 124
 125						} else { // end if Software Add-on is activated
 126
 127							for ( $i = 0; $i < $quantity; $i++ ) {
 128
 129								// Saves meta data for this order to be used by the API Manager if order_key is required
 130				                $meta_data =
 131				                		array( $order->order_key =>
 132				                			array(
 133							                	'user_id'						=> $order->user_id,
 134												'order_id' 						=> $order_id,
 135												'order_key' 					=> $order->order_key,
 136												'license_email' 				=> $order->billing_email,
 137												'_api_software_title_parent' 	=> empty( $software_title_parent ) ? '' : (string) $software_title_parent,
 138												'_api_software_title_var' 		=> empty( $software_title_var ) ? '' : (string) $software_title_var,
 139												'software_title' 				=> empty( $software_title ) ? '' : (string) $software_title,
 140												'parent_product_id'				=> empty( $item_product_id ) ? '' : (int) $item_product_id,
 141												'variable_product_id'			=> empty( $item_variation_id ) ? '' : (int) $item_variation_id,
 142												'current_version'				=> empty( $meta_var['_api_new_version'][0] ) ? '' : (string) $meta_var['_api_new_version'][0],
 143												'_api_activations'				=> empty( $meta_var['_api_activations'][0] ) ? '' : (int) $meta_var['_api_activations'][0],
 144												'_api_activations_parent'		=> '',
 145												'_api_update_permission'		=> 'yes',
 146												'is_variable_product'			=> 'yes',
 147												'license_type'					=> '',
 148												'expires'						=> '',
 149												)
 150				                			);
 151
 152								self::save_order_complete_user_meta( $meta_data, $order->order_key );
 153
 154							}
 155
 156						}
 157
 158					} // end if is_software
 159
 160				} else { // end if variable product
 161
 162					// Start if simple product
 163
 164					$meta = get_post_custom( $item_product_id );
 165
 166					$meta_var = get_post_custom( $item_variation_id );
 167
 168					if ( $meta['_downloadable'][0] == 'yes' || $meta_var['_downloadable'][0] == 'yes' ) {
 169
 170						$quantity = isset( $item['item_meta']['_qty'][0] ) ? absint( $item['item_meta']['_qty'][0] ) : 1;
 171
 172						/**
 173						 * If the parent product has a tile else use the variable product title
 174						 */
 175						if ( isset( $meta['_api_software_title_parent'][0] ) && $meta['_api_software_title_parent'][0] != '' && ! empty( $meta['_api_software_title_parent'][0] ) ) {
 176
 177							$software_title_parent = $meta['_api_software_title_parent'][0];
 178							$software_title = $meta['_api_software_title_parent'][0];
 179
 180						} else if ( isset( $meta_var['_api_software_title_var'][0] ) && $meta_var['_api_software_title_var'][0] != '' && ! empty( $meta_var['_api_software_title_var'][0] ) ) {
 181
 182							$software_title_var = $meta_var['_api_software_title_var'][0];
 183							$software_title = $meta_var['_api_software_title_var'][0];
 184
 185						} else {
 186
 187							$software_title = '';
 188						}
 189
 190						if ( get_option( 'wc_api_manager_software_add_on_license_key' ) == 'yes' && self::is_plugin_active( 'woocommerce-software-add-on/woocommerce-software.php' ) ) {
 191							// Get the order_id
 192							$lic_order_id = $wpdb->get_var( $wpdb->prepare( "
 193								SELECT order_id FROM {$wpdb->prefix}woocommerce_software_licences
 194								WHERE order_id = %d
 195								LIMIT 1
 196							", $order_id ) );
 197
 198							// verify the license has been created before continuing
 199							if ( $lic_order_id ) {
 200
 201								for ( $i = 0; $i < $quantity; $i++ ) {
 202
 203					                $data = array(
 204										'order_id' 				=> $order_id,
 205										'activations_limit'		=> empty( $meta['_api_activations_parent'][0] ) ? '' : (int) $meta['_api_activations_parent'][0],
 206										'software_title' 		=> empty( $software_title ) ? '' : (string) $software_title,
 207										'current_version'		=> empty( $meta['_api_new_version'][0] ) ? '' : (string) $meta['_api_new_version'][0],
 208							        );
 209
 210									self::update_licence_key( $data );
 211
 212									// Saves meta data for this order to be used by the API Manager if Software Add-on license is required
 213					                $meta_data =
 214					                		array( $order->order_key =>
 215					                			array(
 216								                	'user_id'						=> $order->user_id,
 217													'order_id' 						=> $order_id,
 218													'order_key' 					=> $order->order_key,
 219													'license_email' 				=> $order->billing_email,
 220													'_api_software_title_parent' 	=> empty( $software_title_parent ) ? '' : (string) $software_title_parent,
 221													'_api_software_title_var' 		=> empty( $software_title_var ) ? '' : (string) $software_title_var,
 222													'software_title' 				=> empty( $software_title ) ? '' : (string) $software_title,
 223													'parent_product_id'				=> empty( $item_product_id ) ? '' : (int) $item_product_id,
 224													'variable_product_id'			=> empty( $item_variation_id ) ? '' : (int) $item_variation_id,
 225													'current_version'				=> empty( $meta['_api_new_version'][0] ) ? '' : (string) $meta['_api_new_version'][0],
 226													'_api_activations'				=> '',
 227													'_api_activations_parent'		=> empty( $meta['_api_activations_parent'][0] ) ? '' : (int) $meta['_api_activations_parent'][0],
 228													'_api_update_permission'		=> 'yes',
 229													'is_variable_product'			=> 'no',
 230													'license_type'					=> '',
 231													'expires'						=> '',
 232													)
 233					                			);
 234
 235									self::save_order_complete_user_meta( $meta_data, $order->order_key );
 236
 237								}
 238							}
 239
 240						} else { // end if Software Add-on is activated
 241
 242							for ( $i = 0; $i < $quantity; $i++ ) {
 243
 244								// Saves meta data for this order to be used by the API Manager if order_key is required
 245				                $meta_data =
 246				                		array( $order->order_key =>
 247				                			array(
 248							                	'user_id'						=> $order->user_id,
 249												'order_id' 						=> $order_id,
 250												'order_key' 					=> $order->order_key,
 251												'license_email' 				=> $order->billing_email,
 252												'_api_software_title_parent' 	=> empty( $software_title_parent ) ? '' : (string) $software_title_parent,
 253												'_api_software_title_var' 		=> empty( $software_title_var ) ? '' : (string) $software_title_var,
 254												'software_title' 				=> empty( $software_title ) ? '' : (string) $software_title,
 255												'parent_product_id'				=> empty( $item_product_id ) ? '' : (int) $item_product_id,
 256												'variable_product_id'			=> empty( $item_variation_id ) ? '' : (int) $item_variation_id,
 257												'current_version'				=> empty( $meta['_api_new_version'][0] ) ? '' : (string) $meta['_api_new_version'][0],
 258												'_api_activations'				=> '',
 259												'_api_activations_parent'		=> empty( $meta['_api_activations_parent'][0] ) ? '' : (int) $meta['_api_activations_parent'][0],
 260												'_api_update_permission'		=> 'yes',
 261												'is_variable_product'			=> 'no',
 262												'license_type'					=> '',
 263												'expires'						=> '',
 264												)
 265				                			);
 266
 267								self::save_order_complete_user_meta( $meta_data, $order->order_key );
 268
 269							}
 270
 271						}
 272
 273					} // end if is_software
 274
 275				} // end if is not a variable product
 276
 277			}
 278
 279		}
 280
 281	}
 282
 283	/**
 284	 * update_licence_key function.
 285	 *
 286	 * Updates the number of activations per license key according to the API Manager settings
 287	 *
 288	 * @access public
 289	 * @return void
 290	 */
 291	public static function update_licence_key( $data ) {
 292		global $wpdb;
 293
 294		$order_id = $data['order_id'];
 295		$activations = $data['activations_limit'];
 296		$product_id = $data['software_title'];
 297		$software_version = $data['current_version'];
 298
 299		$sql =
 300			"
 301			UPDATE {$wpdb->prefix}woocommerce_software_licences
 302			SET activations_limit = %d,
 303			software_product_id = %s,
 304			software_version = %s
 305			WHERE order_id = %d
 306			LIMIT 1
 307		";
 308
 309		$wpdb->query( $wpdb->prepare( $sql, $activations, $product_id, $software_version, $order_id ) );
 310	}
 311
 312	/**
 313	 * update_licence_key function.
 314	 *
 315	 * Adds user_meta info for download permissions query to the database
 316	 *
 317	 * @access public
 318	 * @return void
 319	 */
 320	public static function save_order_complete_user_meta( $data, $order_key ) {
 321		global $wpdb;
 322
 323		$current_info = self::get_users_data( $data[$order_key]['user_id'] );
 324
 325		$new_info = self::array_merge_recursive_associative( $data, $current_info );
 326
 327		update_user_meta( $data[$order_key]['user_id'], $wpdb->get_blog_prefix() . self::$user_meta_key_orders, $new_info );
 328
 329	}
 330
 331	/**
 332	 * Gets the user order info stored in an array for the $user_id, aka $object_id
 333	 *
 334	 * @since 1.1
 335	 * @param $user_id int
 336	 * @return array
 337	 */
 338	public static function get_users_data( $user_id = 0 ) {
 339		global $wpdb;
 340
 341		if ( $user_id === 0 ) {
 342			$data = array();
 343			return $data;
 344		}
 345
 346		$data = get_metadata( 'user', $user_id, $wpdb->get_blog_prefix() . self::$user_meta_key_orders, true );
 347
 348		if( empty( $data ) )
 349			$data = array();
 350
 351		return $data;
 352	}
 353
 354	/**
 355	 * Gets the order info from the postmeta table with the $post_id, aka $object_id
 356	 *
 357	 * @since 1.1
 358	 * @param $user_id int
 359	 * @return array
 360	 */
 361	public function get_postmeta_data( $post_id = 0 ) {
 362		global $wpdb;
 363
 364		if ( $post_id === 0 ) {
 365			$data = array();
 366			return $data;
 367		}
 368
 369		$data = get_metadata( 'post', $post_id, '', true );
 370
 371		if( empty( $data ) )
 372			$data = array();
 373
 374		return $data;
 375	}
 376
 377	/**
 378	 * Gets the user order info stored in an array for the $user_id, aka $object_id
 379	 *
 380	 * @since 1.1
 381	 * @param $user_id int
 382	 * @return array
 383	 */
 384	public function get_users_activation_data( $user_id = 0, $order_key = 0 ) {
 385		global $wpdb;
 386
 387		if ( $user_id === 0 ) {
 388			$data = array();
 389			return $data;
 390		}
 391
 392		if ( $order_key === 0 ) {
 393			$data = array();
 394			return $data;
 395		}
 396
 397		$data = get_metadata( 'user', $user_id, $wpdb->get_blog_prefix() . self::$user_meta_key_activations . $order_key, true );
 398
 399		if( empty( $data ) )
 400			$data = array();
 401
 402		return $data;
 403	}
 404
 405	/**
 406	 * renew_subscription_order_complete function.
 407	 *
 408	 * Creates license key for renewed subscription orders.
 409	 *
 410	 * @access public
 411	 * @return void
 412	 */
 413	public static function renew_subscription_order_complete( $order_id ) {
 414		global $wpdb;
 415
 416		$order = new WC_Order( $order_id );
 417
 418		if ( count( $order->get_items() ) > 0 ) {
 419
 420			foreach ( $order->get_items() as $item ) {
 421
 422				$item_product_id = ( isset( $item['product_id'] ) ) ? $item['product_id'] : $item['id'];
 423
 424				if ( $item_product_id > 0 ) {
 425
 426					$meta = get_post_custom( $item_product_id );
 427
 428					$quantity = isset( $item['item_meta']['_qty'][0] ) ? absint( $item['item_meta']['_qty'][0] ) : 1;
 429
 430					for ( $i = 0; $i < $quantity; $i++ ) {
 431		                $data = array(
 432							'order_id' 				=> $order_id,
 433							'activation_email'		=> $order->billing_email,
 434							'prefix'				=> empty( $meta['_software_license_key_prefix'][0] ) ? '' : $meta['_software_license_key_prefix'][0],
 435							'software_product_id'	=> empty( $meta['_software_product_id'][0] ) ? '' : $meta['_software_product_id'][0],
 436							'software_version'		=> empty( $meta['_software_version'][0] ) ? '' : $meta['_software_version'][0],
 437							'activations_limit'		=> empty( $meta['_software_activations'][0] ) ? '' : (int) $meta['_software_activations'][0],
 438				        );
 439
 440						$key_id = self::save_licence_key( $data );
 441					}
 442
 443				}
 444
 445			}
 446
 447		}
 448
 449		update_post_meta( $order_id,  'software_processed', 1);
 450
 451	}
 452
 453	/**
 454	 * save_licence_key function.
 455	 *
 456	 * @access public
 457	 * @return void
 458	 */
 459	function save_licence_key( $data ) {
 460		global $wpdb;
 461
 462		$defaults = array(
 463			'order_id' 				=> '',
 464			'activation_email' 		=> '',
 465			'prefix'				=> '',
 466			'licence_key' 			=> self::generate_licence_key(),
 467			'software_product_id' 	=> '',
 468			'software_version'		=> '',
 469			'activations_limit'		=> '',
 470			'created'				=> current_time( 'mysql' )
 471		);
 472
 473		$data = wp_parse_args( $data, $defaults  );
 474
 475		$insert = array(
 476			'order_id' 				=> $data['order_id'],
 477			'activation_email'		=> $data['activation_email'],
 478			'licence_key'			=> $data['prefix'] . $data['licence_key'],
 479			'software_product_id'	=> $data['software_product_id'],
 480			'software_version'		=> $data['software_version'],
 481			'activations_limit'		=> $data['activations_limit'],
 482			'created'				=> $data['created']
 483        );
 484
 485        $format = array(
 486			'%s',
 487			'%s',
 488			'%s',
 489			'%s',
 490			'%s',
 491			'%s',
 492			'%s',
 493			'%s'
 494        );
 495
 496        $wpdb->insert( $wpdb->prefix . 'woocommerce_software_licences',
 497            $insert,
 498            $format
 499        );
 500
 501		return $wpdb->insert_id;
 502	}
 503
 504	/**
 505	 * generates a unique id that is used as the license code
 506	 *
 507	 * @since 1.0
 508	 * @return string the unique ID
 509	 */
 510	function generate_licence_key() {
 511
 512		return sprintf(
 513			'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
 514			mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
 515			mt_rand( 0, 0x0fff ) | 0x4000,
 516			mt_rand( 0, 0x3fff ) | 0x8000,
 517			mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
 518		);
 519	}
 520
 521	/**
 522	 * Find post_id that matches api_key and activation_email
 523	 *
 524	 * @access public
 525	 * @param mixed license_key
 526	 * @param mixed activation_email
 527	 * @return integer $post_id which is the same as the product_id
 528	 */
 529	public function get_post_id( $api_key, $activation_email ) {
 530		global $wpdb;
 531
 532		$order_id = $wpdb->get_var( $wpdb->prepare( "
 533			SELECT order_id FROM {$wpdb->prefix}woocommerce_software_licences
 534			WHERE licence_key = %s
 535			AND activation_email = %s LIMIT 1
 536		", $api_key, $activation_email ) );
 537
 538		$post_id = $wpdb->get_var( $wpdb->prepare( "
 539			SELECT product_id FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
 540			WHERE order_id = %s
 541			LIMIT 1
 542		", $order_id ) );
 543
 544		if ( ! $post_id ) return false;
 545
 546		return $post_id;
 547	}
 548
 549	/**
 550	 * Find order_id that matches api_key and activation_email
 551	 *
 552	 * @access public
 553	 * @param mixed license_key
 554	 * @param mixed activation_email
 555	 * @return integer $order_id
 556	 */
 557	public function get_order_id( $api_key, $activation_email ) {
 558		global $wpdb;
 559
 560		$order_id = $wpdb->get_var( $wpdb->prepare( "
 561			SELECT order_id FROM {$wpdb->prefix}woocommerce_software_licences
 562			WHERE licence_key = %s
 563			AND activation_email = %s LIMIT 1
 564		", $api_key, $activation_email ) );
 565
 566		if ( ! $order_id ) return false;
 567
 568		return $order_id;
 569	}
 570
 571	/**
 572	 * Find post_id which can match a purchase ID or a product ID
 573	 *
 574	 * @access public
 575	 * @param mixed meta_key
 576	 * @param mixed meta_value
 577	 * @return integer $post_id which is the same as the product_id
 578	 */
 579	public function get_post_id_by( $meta_key, $meta_value ) {
 580		global $wpdb;
 581
 582		$post_id = $wpdb->get_var( $wpdb->prepare( "
 583			SELECT post_id FROM {$wpdb->postmeta}
 584			WHERE meta_key = %s
 585			AND meta_value = %s LIMIT 1
 586		", $meta_key, $meta_value ) );
 587
 588		if ( ! $post_id ) return false;
 589
 590		return $post_id;
 591	}
 592
 593	/**
 594	 * Find file download id (am_key)
 595	 *
 596	 * @access public
 597	 * @param $post_id (integer)
 598	 * @return array $download_id (limited to first value in array)
 599	 */
 600	public function get_download_id( $post_id ) {
 601
 602		$file_path = get_post_meta( $post_id, '_file_paths', true );
 603
 604		if ( is_array( $file_path ) ) {
 605			foreach ( $file_path as $key => $value ) {
 606				$path[] = $key;
 607			}
 608		}
 609
 610		if ( ! $path[0] ) return false;
 611
 612		return $path[0];
 613	}
 614
 615	/**
 616	 * Find file download path, or download link, usually the same value
 617	 *
 618	 * @access public
 619	 * @param mixed $software_product_id, i.e. Simple Comments, or  $post->ID if Software add-on not installed
 620	 * @return array $file_path (limited to first value in array)
 621	 */
 622	public function get_file_path( $software_product_id, $software_add_on = true ) {
 623
 624		if ( $software_add_on ) { // use the product id, i.e. Simple Comments
 625			$product_id = self::get_post_id( $software_product_id );
 626			if ( ! $product_id ) return false;
 627
 628			$file_path = get_post_meta( $product_id, '_file_paths', true );
 629		} else { // use post->ID
 630			$file_path = get_post_meta( $software_product_id, '_file_paths', true );
 631		}
 632
 633		if ( is_array( $file_path ) ) {
 634			foreach ( $file_path as $key => $value ) {
 635				$path[] = $value;
 636			}
 637		}
 638
 639		if ( ! $path[0] ) return false;
 640
 641		return $path[0];
 642	}
 643
 644	/**
 645	 * verify_licence_key function.
 646	 *
 647	 * @access public
 648	 * @param mixed $api_key
 649	 * @param mixed $activation_email
 650	 * @return bool
 651	 */
 652	public function verify_license_key( $api_key, $activation_email ) {
 653    	global $wpdb;
 654
 655		$sql =
 656			"
 657			SELECT licence_key FROM {$wpdb->prefix}woocommerce_software_licences
 658			WHERE licence_key = %s
 659			AND activation_email = %s
 660			LIMIT 1
 661			";
 662
 663		$key = $wpdb->get_var( $wpdb->prepare( $sql, $api_key, $activation_email ) );
 664
 665		if ( $key == $api_key )
 666			return true;
 667
 668		return false;
 669	}
 670
 671	/**
 672	 * get_order_number function.
 673	 *
 674	 * @access public
 675	 * @param mixed $api_key
 676	 * @param mixed $activation_email
 677	 * @return string
 678	 */
 679	public function get_order_number( $api_key, $activation_email ) {
 680    	global $wpdb;
 681
 682		$order_id = $wpdb->get_var( $wpdb->prepare( "
 683			SELECT order_id FROM {$wpdb->prefix}woocommerce_software_licences
 684			WHERE licence_key = %s
 685			AND activation_email = %s
 686			LIMIT 1
 687		", $api_key, $activation_email ) );
 688
 689		$order_number = $wpdb->get_var( $wpdb->prepare( "
 690			SELECT meta_value FROM {$wpdb->postmeta}
 691			WHERE post_id = %s
 692			AND meta_key = '_order_key'
 693			LIMIT 1
 694		", $order_id ) );
 695
 696		return $order_number;
 697	}
 698
 699	/**
 700	 * download_count function.
 701	 *
 702	 * @access public
 703	 * @param mixed $order_id
 704	 * @param mixed $order_key
 705	 * @return integer or boolean
 706	 */
 707	public function get_download_count( $order_id, $order_key ) {
 708    	global $wpdb;
 709
 710		$download_count = $wpdb->get_var( $wpdb->prepare( "
 711			SELECT download_count FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
 712			WHERE order_id = %s
 713			AND order_key = %s
 714			LIMIT 1
 715		", $order_id, $order_key ) );
 716
 717		if ( isset( $download_count ) )
 718			return $download_count;
 719
 720		return false;
 721	}
 722
 723	/**
 724	 * create_url function to properly format download url
 725	 *
 726	 * @access public
 727	 * @param mixed $api_key
 728	 * @param mixed $activation_email
 729	 * @param mixed $product_id
 730	 * @return url + query string
 731	 */
 732	public function create_url( $api_key, $activation_email, $product_id, $download_id = '' ) {
 733		global $wpdb;
 734
 735		if ( stristr( $api_key, 'order_') ) {
 736
 737			$order_key = $api_key;
 738
 739		} else if ( self::is_plugin_active( 'woocommerce-software-add-on/woocommerce-software.php' ) ) {
 740
 741			$order_key = self::get_order_number( $api_key, $activation_email );
 742
 743		}
 744
 745		$sql = "
 746			SELECT product_id,order_id,downloads_remaining,user_id,download_count,access_expires,download_id
 747			FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
 748			WHERE user_email = %s
 749			AND order_key = %s
 750			AND product_id = %s";
 751
 752		$args = array(
 753			$activation_email,
 754			$order_key,
 755			$product_id
 756		);
 757
 758		if ( $download_id ) {
 759			// backwards compatibility for existing download URLs
 760			$sql .= " AND download_id = %s";
 761			$args[] = $download_id;
 762		}
 763
 764		//$result = $wpdb->get_row( $wpdb->prepare( $sql, $args ), ARRAY_A );
 765		$result = $wpdb->get_row( $wpdb->prepare( $sql, $args ) );
 766
 767		//$result = get_object_vars( $download_result );
 768
 769		/**
 770		 * Since adding the ARRAY_A flag an associative array is returned rather than an object
 771		 *
 772		 * 	$download_result returns:
 773		 * stdClass Object
 774		 *	(
 775		 *		[product_id] =>
 776		 *		[order_id] =>
 777		 *		[downloads_remaining] =>
 778		 *		[user_id] =>
 779		 *		[download_count] =>
 780		 *		[access_expires] =>
 781		 *		[download_id] =>
 782		 *	)
 783		 *	get_object_vars() puts oject into an array
 784		 */
 785
 786		$url_args = array(
 787			'am_download_file' 	=> $result->product_id,
 788			'am_order' 			=> $order_key,
 789			'am_email' 			=> $activation_email,
 790		);
 791
 792		if ( $result->download_id != '' ) {
 793			$url_args['am_key'] = $result->download_id;
 794		}
 795
 796		return site_url() . '/?' . http_build_query( $url_args, '', '&' );
 797	}
 798
 799	/**
 800	 * Checks if a plugin is activated
 801	 *
 802	 * @since 1.1
 803	 */
 804	public static function is_plugin_active( $slug ) {
 805		$active_plugins = (array) get_option( 'active_plugins', array() );
 806
 807		if ( is_multisite() )
 808			$active_plugins = array_merge( $active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
 809
 810		return in_array( $slug, $active_plugins ) || array_key_exists( $slug, $active_plugins );
 811	}
 812
 813	/**
 814	 * Checks if page content exists
 815	 *
 816	 * @since 1.1
 817	 */
 818	public function get_page_content( $page_obj ) {
 819
 820		if ( isset( $page_obj  ) && is_object( $page_obj ) ) {
 821
 822			if ( ! empty( $page_obj->post_content ) ) {
 823
 824				return $page_obj->post_content;
 825
 826			} else {
 827
 828				return '';
 829
 830			}
 831
 832		} else {
 833
 834			return '';
 835
 836		}
 837
 838	}
 839
 840	/**
 841	 * Merges arrays recursively with an associative key
 842	 * To merge arrays that are numerically indexed use the PHP array_merge_recursive() function
 843	 *
 844	 * @since 1.1
 845	 * @param $array1 Array
 846	 * @param $array2 Array
 847	 * @return array
 848	 */
 849	public static function array_merge_recursive_associative( $array1, $array2 ) {
 850
 851		$merged_arrays = $array1;
 852
 853		if ( is_array( $array2 ) ) {
 854			foreach ( $array2 as $key => $val ) {
 855				if ( is_array( $array2[$key] ) ) {
 856					$merged_arrays[$key] = ( isset( $merged_arrays[$key] ) && is_array( $merged_arrays[$key] ) ) ? self::array_merge_recursive_associative( $merged_arrays[$key], $array2[$key] ) : $array2[$key];
 857				} else {
 858					$merged_arrays[$key] = $val;
 859				}
 860			}
 861		}
 862
 863		return $merged_arrays;
 864	}
 865
 866	/**
 867	 * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
 868	 * keys to arrays rather than overwriting the value in the first array with the duplicate
 869	 * value in the second array, as array_merge does. I.e., with array_merge_recursive,
 870	 * this happens (documented behavior):
 871	 *
 872	 * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
 873	 *     => array('key' => array('org value', 'new value'));
 874	 *
 875	 * array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
 876	 * Matching keys' values in the second array overwrite those in the first array, as is the
 877	 * case with array_merge, i.e.:
 878	 *
 879	 * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
 880	 *     => array('key' => array('new value'));
 881	 *
 882	 * Parameters are passed by reference, though only for performance reasons. They're not
 883	 * altered by this function.
 884	 *
 885	 * @param array $array1
 886	 * @param array $array2
 887	 * @return array
 888	 * @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
 889	 * @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
 890	 * @since 1.1.1
 891	 */
 892	public function array_merge_recursive_distinct ( array &$array1, array &$array2 ) {
 893		$merged = $array1;
 894
 895		foreach ( $array2 as $key => &$value ) {
 896			if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) ) {
 897				$merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value );
 898			} else {
 899				$merged [$key] = $value;
 900			}
 901		}
 902
 903		return $merged;
 904	}
 905
 906	/**
 907	 * Experimental
 908	 * @since 1.1.1
 909	 * @param  [type]  $needle   [description]
 910	 * @param  [type]  $haystack [description]
 911	 * @param  boolean $strict   [description]
 912	 * @return [type]            [description]
 913	 */
 914	public function in_array_recursive( $needle, $haystack, $strict = false ) {
 915
 916		foreach ( $haystack as $item ) {
 917
 918			if ( ( $strict ? $item === $needle : $item == $needle ) || ( is_array( $item ) && self::in_array_recursive( $needle, $item, $strict ) ) ) {
 919
 920				return true;
 921
 922			}
 923
 924		}
 925
 926		return false;
 927	}
 928
 929	/**
 930	 * Removes element from array based on key
 931	 * @since 1.1
 932	 * @return array New array minus removed elements
 933	 *
 934	 * For example:
 935	 *
 936	 * $fruit_inventory = array(
 937	 *	  'apples' => 52,
 938	 *	  'bananas' => 78,
 939	 *	  'peaches' => 'out of season',
 940	 *	  'pears' => 'out of season',
 941	 *	  'oranges' => 'no longer sold',
 942	 *	  'carrots' => 15,
 943	 *	  'beets' => 15,
 944	 *	);
 945	 *
 946	 * $fruit_inventory = array_remove_by_key($fruit_inventory,
 947     *                              "beets",
 948     *                              "carrots");
 949	 */
 950	public function array_remove_by_key() {
 951
 952		$args  = func_get_args();
 953
 954		return array_diff_key( $args[0], array_flip( array_slice( $args, 1 ) ) );
 955
 956	}
 957
 958	/**
 959	 * Removes element from array based on value
 960	 * @since 1.1
 961	 * @return array New array minus removed elements
 962	 * For example:
 963	 *
 964	 * $fruit_inventory = array(
 965	 *	  'apples' => 52,
 966	 *	  'bananas' => 78,
 967	 *	  'peaches' => 'out of season',
 968	 *	  'pears' => 'out of season',
 969	 *	  'oranges' => 'no longer sold',
 970	 *	  'carrots' => 15,
 971	 *	  'beets' => 15,
 972	 *	);
 973	 *
 974	 * $fruit_inventory = array_remove_by_value($fruit_inventory,
 975     *                                 "out of season",
 976     *                                 "no longer sold");
 977	 */
 978	public function array_remove_by_value() {
 979
 980		$args = func_get_args();
 981
 982		return array_diff( $args[0], array_slice( $args, 1 ) );
 983
 984	}
 985
 986	/**
 987	 * array_search_multi Finds if a value matched with a needle exists in a multidimensional array
 988	 * @param  array $array  multidimensional array (for simple array use array_search)
 989	 * @param  mixed $value  value to search for
 990	 * @param  mixed $needle needle that needs to match value in array
 991	 * @since 1.1.1
 992	 * @return boolean
 993	 */
 994	public function array_search_multi( $array, $value, $needle ) {
 995
 996		foreach( $array as $index_key => $value_key ) {
 997
 998			if ( $value_key[$value] === $needle ) return true;
 999
1000		}
1001
1002		return false;
1003	}
1004
1005	/**
1006	 * get_array_search_multi Finds a key for a value matched by a needle in a multidimensional array
1007	 * @param  array $array  multidimensional array (for simple array use array_search)
1008	 * @param  mixed $value  value to search for
1009	 * @param  mixed $needle needle that needs to match value in array
1010	 * @since 1.1.1
1011	 * @return mixed
1012	 */
1013	public function get_key_array_search_multi( $array, $value, $needle ) {
1014
1015		foreach( $array as $index_key => $value_key ) {
1016
1017			if ( $value_key[$value] === $needle ) return $value_key;
1018
1019		}
1020
1021		return false;
1022	}
1023
1024	/**
1025	 * Gets the status of a checkbox
1026	 *
1027	 * @since 1.1
1028	 * @param $product_id int
1029	 * @param $meta_key string
1030	 * @return boolean
1031	 */
1032	public function get_product_checkbox_status( $post_id, $meta_key ) {
1033
1034		$result = get_post_meta( $post_id, $meta_key, true );
1035
1036		if ( $result == 'yes' )
1037			return true;
1038		else
1039			return false;
1040
1041	}
1042
1043	/**
1044	 * get_order_info_by_email_with_order_key Gets the user order info
1045	 * @param  string $activation_email license email
1046	 * @param  string $order_key        order key
1047	 * @return array                    array populated with user purchase info
1048	 */
1049	public function get_order_info_by_email_with_order_key( $activation_email, $order_key ) {
1050
1051		if ( isset( $activation_email ) )
1052			$user = get_user_by( 'email', $activation_email ); // returns $user->ID
1053		else
1054			return false;
1055
1056		if ( ! is_object( $user ) ) return false;
1057
1058		// Check if this is an order_key
1059		if ( isset( $order_key ) && stristr( $order_key, 'order_') ) {
1060
1061			$user_orders = self::get_users_data( $user->ID );
1062
1063			if ( isset( $user_orders ) && ! empty( $user_orders ) )
1064				return $user_orders[$order_key]; // returns a single order info array identified by order_key
1065			else
1066				return false;
1067
1068		}
1069
1070		return false;
1071
1072	}
1073
1074	/**
1075	 * Determine subscription status using order_id = post_id
1076	 *
1077	 * For Suscriptions > 1.4
1078	 *
1079	 * @access public
1080	 * @param int order_id
1081	 * @since 1.1.1
1082	 * @return string subscription status
1083	 */
1084	public function get_subscription_status( $order_id ) {
1085		global $wpdb;
1086
1087		$order_item_id = $wpdb->get_var( $wpdb->prepare( "
1088			SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items
1089			WHERE order_id = %d
1090			LIMIT 1
1091		", $order_id ) );
1092
1093		$status = $wpdb->get_var( $wpdb->prepare( "
1094			SELECT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta
1095			WHERE order_item_id = %d
1096			AND meta_key = %s LIMIT 1
1097		", $order_item_id, '_subscription_status' ) );
1098
1099		if ( isset( $status ) && ! empty( $status ) )
1100			return $status;
1101		else
1102			return false;
1103
1104	}
1105
1106	/**
1107	 * Nonce URL
1108	 * @param  mixed $args string or array
1109	 * @see http://codex.wordpress.org/Function_Reference/add_query_arg
1110	 * @return string
1111	 * @since 1.2.1
1112	 */
1113	public function nonce_url( $args ) {
1114
1115		$action_url = wp_nonce_url( add_query_arg( $args ) );
1116
1117		return $action_url;
1118
1119	}
1120
1121	/**
1122	 * Finds the default order_ prefix or a unique prefix that was created
1123	 * by the woocommerce_generate_order_key filter
1124	 *
1125	 * example $uniqid = $this->get_uniqid_prefix( $product_post_meta['_order_key'][0], '_' );
1126	 *
1127	 * @access public
1128	 * @param  mixed $haystack
1129	 * @param  mixed $needle
1130	 * @return mixed
1131	 */
1132	public function get_uniqid_prefix( $haystack, $needle ) {
1133
1134		$pos = stripos( $haystack, $needle ) + 1;
1135
1136		return trim( substr( $haystack, 0, $pos ) );
1137
1138	}
1139
1140	/**
1141	 * Allows the customer to delete a domain name activated for an order on their My Account dashbaord
1142	 * @return void or error message
1143	 * @since 1.2.1
1144	 */
1145	public static function delete_my_account_url() {
1146		global $woocommerce, $wpdb, $wc_api_manager_helpers, $woocommerce_plugin_update_api_manager;
1147
1148		if ( isset( $_GET['domain'] ) && isset( $_GET['instance'] ) && isset( $_GET['order_key'] ) && isset( $_GET['user_id'] ) && isset( $_GET['_wpnonce'] ) ) {
1149
1150			if ( wp_verify_nonce( $_GET['_wpnonce'] ) === false )
1151				$woocommerce->add_error( __( 'The domain name could not be deleted.', $woocommerce_plugin_update_api_manager->text_domain ) );
1152
1153			$domain 	= sanitize_text_field( $_GET['domain'] );
1154			$instance 	= sanitize_text_field( $_GET['instance'] );
1155			$order_key 	= sanitize_text_field( $_GET['order_key'] );
1156			$user_id 	= intval( $_GET['user_id'] );
1157
1158			$current_info = self::get_users_activation_data( $user_id, $order_key );
1159
1160	    	if ( ! empty( $current_info ) ) {
1161
1162				$active_activations = 0;
1163
1164		    	foreach ( $current_info as $key => $activations ) {
1165
1166		    		if ( $activations['activation_active'] == 1 && $order_key == $activations['order_key'] ) {
1167
1168						$active_activations++;
1169
1170		    		}
1171
1172		    	}
1173
1174	    		foreach ( $current_info as $key => $activation_info ) {
1175
1176	    			if ( $active_activations <= 1 && $activation_info['activation_active'] == 1 && $activation_info['instance'] == $instance && $activation_info['activation_domain'] == $domain ) {
1177
1178						delete_user_meta( $user_id, $wpdb->get_blog_prefix() . self::$user_meta_key_activations . $order_key );
1179
1180						wp_safe_redirect( get_permalink( woocommerce_get_page_id( 'myaccount' ) ) );
1181
1182						break;
1183
1184						exit();
1185
1186					} else if ( $activation_info['activation_active'] == 1 && $activation_info['activation_active'] == 1 && $activation_info['instance'] == $instance && $activation_info['activation_domain'] == $domain ) {
1187
1188						// Delete the activation data array
1189		    			unset( $current_info[$key] );
1190
1191			    		// Re-index the numerical array keys:
1192						$new_info = array_values( $current_info );
1193
1194						update_user_meta( $user_id, $wpdb->get_blog_prefix() . self::$user_meta_key_activations . $order_key, $new_info );
1195
1196						wp_safe_redirect( get_permalink( woocommerce_get_page_id( 'myaccount' ) ) );
1197
1198						break;
1199
1200						exit();
1201
1202					}
1203
1204	    		} // end foreach
1205
1206			}
1207
1208		}
1209
1210	}
1211
1212	/**
1213	 * Download a file - hook into init function.
1214	 * variation of woocommerce_download_product() function
1215	 *
1216	 * No login required for Plugin Updates since authentication is handled by the APIs
1217	 * Download restrictions controlled by WooCommerce order screen
1218	 *
1219	 * @access public
1220	 * @return void
1221	 */
1222	public static function download_product() {
1223		global $woocommerce_plugin_update_api_manager;
1224
1225		if ( isset( $_GET['am_download_file'] ) && isset( $_GET['am_order'] ) && isset( $_GET['am_email'] ) ) {
1226
1227			global $wpdb, $is_IE;
1228
1229			$product_id           = (int) urldecode($_GET['am_download_file']);
1230			$order_key            = urldecode( $_GET['am_order'] );
1231			$email                = sanitize_email( str_replace( ' ', '+', urldecode( $_GET['am_email'] ) ) );
1232			$download_id          = isset( $_GET['am_key'] ) ? preg_replace( '/\s+/', ' ', urldecode( $_GET['am_key'] ) ) : '';
1233			$_product             = get_product( $product_id );
1234			$file_download_method = apply_filters( 'woocommerce_file_download_method', get_option( 'woocommerce_file_download_method' ), $product_id );
1235
1236			if ( ! is_email( $email) )
1237				wp_die( __( 'Invalid email address.', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="' . home_url() . '">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1238
1239			$query = "
1240				SELECT order_id,downloads_remaining,user_id,download_count,access_expires,download_id
1241				FROM " . $wpdb->prefix . "woocommerce_downloadable_product_permissions
1242				WHERE user_email = %s
1243				AND order_key = %s
1244				AND product_id = %s";
1245			$args = array(
1246				$email,
1247				$order_key,
1248				$product_id
1249			);
1250
1251			if ( $download_id ) {
1252				// backwards compatibility for existing download URLs
1253				$query .= " AND download_id = %s";
1254				$args[] = $download_id;
1255			}
1256
1257			$download_result = $wpdb->get_row( $wpdb->prepare( $query, $args ) );
1258
1259			if ( ! $download_result )
1260				wp_die( __( 'Invalid download.', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="'.home_url().'">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1261
1262			$download_id 			= $download_result->download_id;
1263			$order_id 				= $download_result->order_id;
1264			$downloads_remaining 	= $download_result->downloads_remaining;
1265			$download_count 		= $download_result->download_count;
1266			$user_id 				= $download_result->user_id;
1267			$access_expires 		= $download_result->access_expires;
1268
1269			// if ( $user_id && get_option( 'woocommerce_downloads_require_login' ) == 'yes' ) {
1270
1271			// 	if ( ! is_user_logged_in() )
1272			// 		wp_die( __( 'You must be logged in to download files.', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="' . wp_login_url( get_permalink( woocommerce_get_page_id( 'myaccount' ) ) ) . '">' . __( 'Login &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1273
1274			// 	elseif ( $user_id != get_current_user_id() )
1275			// 		wp_die( __( 'This is not your download link.', $woocommerce_plugin_update_api_manager->text_domain ) );
1276
1277			// }
1278
1279			if ( ! get_post( $product_id ) )
1280				wp_die( __( 'Product no longer exists.', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="' . home_url() . '">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1281
1282			if ( $order_id ) {
1283				$order = new WC_Order( $order_id );
1284
1285				if ( ! $order->is_download_permitted() || $order->post_status != 'publish' )
1286					wp_die( __( 'Invalid order.', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="' . home_url() . '">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1287			}
1288
1289			if ( $downloads_remaining == '0' )
1290				wp_die( __( 'Sorry, you have reached your download limit for this file', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="'.home_url().'">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1291
1292			if ( $access_expires > 0 && strtotime( $access_expires) < current_time( 'timestamp' ) )
1293				wp_die( __( 'Sorry, this download has expired', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="' . home_url() . '">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1294
1295			if ( $downloads_remaining > 0 ) {
1296				$wpdb->update( $wpdb->prefix . "woocommerce_downloadable_product_permissions", array(
1297					'downloads_remaining' => $downloads_remaining - 1,
1298				), array(
1299					'user_email' 	=> $email,
1300					'order_key' 	=> $order_key,
1301					'product_id' 	=> $product_id,
1302					'download_id' 	=> $download_id
1303				), array( '%d' ), array( '%s', '%s', '%d', '%s' ) );
1304			}
1305
1306			// Count the download
1307			$wpdb->update( $wpdb->prefix . "woocommerce_downloadable_product_permissions", array(
1308				'download_count' => $download_count + 1,
1309			), array(
1310				'user_email' 	=> $email,
1311				'order_key' 	=> $order_key,
1312				'product_id' 	=> $product_id,
1313				'download_id' 	=> $download_id
1314			), array( '%d' ), array( '%s', '%s', '%d', '%s' ) );
1315
1316			// Trigger action
1317			do_action( 'download_product', $email, $order_key, $product_id, $user_id, $download_id, $order_id );
1318
1319			// Get the download URL and try to replace the url with a path
1320			$file_path = $_product->get_file_download_path( $download_id );
1321
1322			if ( ! $file_path )
1323				wp_die( __( 'No file defined', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="'.home_url().'">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1324
1325			// Redirect to the file...
1326			if ( $file_download_method == "redirect" ) {
1327				header( 'Location: ' . $file_path );
1328				exit;
1329			}
1330
1331			// ...or serve it
1332			if ( ! is_multisite() ) {
1333
1334				/*
1335				 * Download file may be either http or https.
1336				 * site_url() depends on whether the page containing the download (ie; My Account) is served via SSL because WC
1337				 * modifies site_url() via a filter to force_ssl.
1338				 * So blindly doing a str_replace is incorrect because it will fail when schemes are mismatched. This code
1339				 * handles the various permutations.
1340				 */
1341				$scheme = parse_url( $file_path, PHP_URL_SCHEME );
1342
1343				if ( $scheme ) {
1344					$site_url = set_url_scheme( site_url( '' ), $scheme );
1345				} else {
1346					$site_url = is_ssl() ? str_replace( 'https:', 'http:', site_url() ) : site_url();
1347				}
1348
1349				$file_path   = str_replace( trailingslashit( $site_url ), ABSPATH, $file_path );
1350
1351			} else {
1352
1353				$network_url = is_ssl() ? str_replace( 'https:', 'http:', network_admin_url() ) : network_admin_url();
1354				$upload_dir  = wp_upload_dir();
1355
1356				// Try to replace network url
1357				$file_path   = str_replace( trailingslashit( $network_url ), ABSPATH, $file_path );
1358
1359				// Now try to replace upload URL
1360				$file_path   = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $file_path );
1361			}
1362
1363			// See if its local or remote
1364			if ( strstr( $file_path, 'http:' ) || strstr( $file_path, 'https:' ) || strstr( $file_path, 'ftp:' ) ) {
1365				$remote_file = true;
1366			} else {
1367				$remote_file = false;
1368
1369				// Remove Query String
1370				if ( strstr( $file_path, '?' ) )
1371					$file_path = current( explode( '?', $file_path ) );
1372
1373				$file_path   = realpath( $file_path );
1374			}
1375
1376			$file_extension  = strtolower( substr( strrchr( $file_path, "." ), 1 ) );
1377			$ctype           = "application/force-download";
1378
1379			foreach ( get_allowed_mime_types() as $mime => $type ) {
1380				$mimes = explode( '|', $mime );
1381				if ( in_array( $file_extension, $mimes ) ) {
1382					$ctype = $type;
1383					break;
1384				}
1385			}
1386
1387			// Start setting headers
1388			if ( ! ini_get('safe_mode') )
1389				@set_time_limit(0);
1390
1391			if ( function_exists( 'get_magic_quotes_runtime' ) && get_magic_quotes_runtime() )
1392				@set_magic_quotes_runtime(0);
1393
1394			if( function_exists( 'apache_setenv' ) )
1395				@apache_setenv( 'no-gzip', 1 );
1396
1397			@session_write_close();
1398			@ini_set( 'zlib.output_compression', 'Off' );
1399			@ob_end_clean();
1400
1401			if ( ob_get_level() )
1402				@ob_end_clean(); // Zip corruption fix
1403
1404			if ( $is_IE && is_ssl() ) {
1405				// IE bug prevents download via SSL when Cache Control and Pragma no-cache headers set.
1406				header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
1407				header( 'Cache-Control: private' );
1408			} else {
1409				nocache_headers();
1410			}
1411
1412			$file_name = basename( $file_path );
1413
1414			if ( strstr( $file_name, '?' ) )
1415				$file_name = current( explode( '?', $file_name ) );
1416
1417			header( "Robots: none" );
1418			header( "Content-Type: " . $ctype );
1419			header( "Content-Description: File Transfer" );
1420			header( "Content-Disposition: attachment; filename=\"" . $file_name . "\";" );
1421			header( "Content-Transfer-Encoding: binary" );
1422
1423	        if ( $size = @filesize( $file_path ) )
1424	        	header( "Content-Length: " . $size );
1425
1426			if ( $file_download_method == 'xsendfile' ) {
1427
1428				// Path fix - kudos to Jason Judge
1429	         	if ( getcwd() )
1430	         		$file_path = trim( preg_replace( '`^' . getcwd() . '`' , '', $file_path ), '/' );
1431
1432	            header( "Content-Disposition: attachment; filename=\"" . $file_name . "\";" );
1433
1434	            if ( function_exists( 'apache_get_modules' ) && in_array( 'mod_xsendfile', apache_get_modules() ) ) {
1435
1436	            	header("X-Sendfile: $file_path");
1437	            	exit;
1438
1439	            } elseif ( stristr( getenv( 'SERVER_SOFTWARE' ), 'lighttpd' ) ) {
1440
1441	            	header( "X-Lighttpd-Sendfile: $file_path" );
1442	            	exit;
1443
1444	            } elseif ( stristr( getenv( 'SERVER_SOFTWARE' ), 'nginx' ) || stristr( getenv( 'SERVER_SOFTWARE' ), 'cherokee' ) ) {
1445
1446	            	header( "X-Accel-Redirect: /$file_path" );
1447	            	exit;
1448
1449	            }
1450	        }
1451
1452	        if ( $remote_file )
1453	        	@woocommerce_readfile_chunked( $file_path ) or header( 'Location: ' . $file_path );
1454	        else
1455	        	@woocommerce_readfile_chunked( $file_path ) or wp_die( __( 'File not found', $woocommerce_plugin_update_api_manager->text_domain ) . ' <a href="' . home_url() . '">' . __( 'Go to homepage &rarr;', $woocommerce_plugin_update_api_manager->text_domain ) . '</a>' );
1456
1457	        exit;
1458		}
1459	}
1460
1461}
1462
1463$GLOBALS['wc_api_manager_helpers'] = new WC_Api_Manager_Helpers();