/**
 * Removes add to cart buttons from single product page if:
 *	- the product is sold-individually, 
 *	- has a voucher attached, and
 *	- the product is already in the cart
 * to prevent multiple purchases of a voucher in an order.
 */
function sv_wc_pdf_product_vouchers_disable_multiple_quantities()
{
    // Bail if PDF Product vouchers isn't active
    if (!function_exists('wc_pdf_product_vouchers')) {
        return;
    }
    // Get the ID for the current product
    global $product;
    $product_id = $product->is_type('variation') ? $product->variation_id : $product->id;
    // bail unless there's a voucher and the product is sold individually
    if (!($product->is_sold_individually() && WC_PDF_Product_Vouchers_Product::has_voucher($product))) {
        return;
    }
    // check if the item is already in the cart
    foreach (WC()->cart->get_cart() as $cart_key => $cart_item) {
        $cart_product = $cart_item['data'];
        // if our product ID matches an item in the cart, disable purchasing
        if ($product->id === $cart_product->id) {
            // remove add to cart button
            remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30);
            // add a notice that you can only purchase one
            function no_purchase_message()
            {
                echo '<div class="woocommerce-info">Looks like this product is already in your cart! You can only purchase one per order.</div>';
            }
            add_action('woocommerce_single_product_summary', 'no_purchase_message', 30);
        }
    }
}
 /**
  * Pluggable function to render the frontend product page voucher fields
  *
  * @since 1.2
  * @param WC_Product $product the voucher product
  */
 function wc_pdf_product_vouchers_render_product_voucher_fields($product)
 {
     if ($product->is_type('variable')) {
         foreach ($product->get_children() as $variation_product_id) {
             $products[] = wc_get_product($variation_product_id);
         }
     } else {
         $products[] = $product;
     }
     foreach ($products as $product) {
         $voucher = WC_PDF_Product_Vouchers_Product::get_voucher($product);
         if ($voucher) {
             $fields = $voucher->get_user_input_voucher_fields();
             $images = $voucher->get_image_urls();
             if ($fields || $images) {
                 // load the template file
                 wc_get_template('single-product/product-voucher.php', array('product' => $product, 'product_id' => isset($product->variation_id) ? $product->variation_id : $product->id, 'voucher' => $voucher, 'fields' => $fields, 'images' => $images), '', wc_pdf_product_vouchers()->get_plugin_path() . '/templates/');
             }
         }
     }
 }
 /**
  * Called from the customer account page, this adds the date to the
  * voucher links so they are a little bit easier to distinguish from one
  * another.  Also filter out links for voucher files that don't exist for
  * whatever reason.
  *
  * @since 1.2
  * @param array $downloads available downloads
  *
  * @return array available downloads
  */
 public function customer_get_downloadable_products($downloads)
 {
     $new_downloads = array();
     foreach ($downloads as $download) {
         $product = wc_get_product($download['product_id']);
         // is the product a voucher product?
         if (false !== strpos($download['download_id'], 'wc_vouchers_') && WC_PDF_Product_Vouchers_Product::has_voucher($product)) {
             $order = wc_get_order($download['order_id']);
             // download id looks like "wc_vouchers_{voucher number}"
             $voucher = WC_PDF_Product_Vouchers_Order::get_voucher_by_voucher_number($order, str_replace('wc_vouchers_', '', $download['download_id']));
             if ($voucher && $voucher->file_exists(WC_PDF_Product_Vouchers::get_uploads_path())) {
                 $download['download_name'] .= ' (' . sprintf(_x('Voucher %s %s', 'Voucher number and date', WC_PDF_Product_Vouchers::TEXT_DOMAIN), $voucher->get_voucher_number(), date_i18n(get_option('date_format'), strtotime($order->order_date))) . ')';
                 $new_downloads[] = $download;
             }
         } else {
             // regular file
             $new_downloads[] = $download;
         }
     }
     return $new_downloads;
 }
 /**
  * Add any user-supplied voucher field data to the cart item data, to
  * set in the session
  *
  * @since 1.2
  * @param array $cart_item_data associative-array of name/value pairs of cart item data
  * @param int $product_id the product identifier
  * @param int $variation_id optional product variation identifer
  *
  * @return array associative array of name/value pairs of cart item
  *         data to set in the session
  */
 public function add_cart_item_voucher_data($cart_item_data, $product_id, $variation_id)
 {
     $_product_id = $variation_id ? $variation_id : $product_id;
     $product = wc_get_product($_product_id);
     // is this a voucher product?
     if (WC_PDF_Product_Vouchers_Product::has_voucher($product)) {
         $voucher = WC_PDF_Product_Vouchers_Product::get_voucher($product);
         // record the voucher id
         $cart_item_data['voucher_id'] = $voucher->id;
         // set the selected voucher image id, or default to the main one if the voucher was added from the catalog
         $cart_item_data['voucher_image_id'] = isset($_POST['voucher_image'][$_product_id]) ? $_POST['voucher_image'][$_product_id] : $voucher->image_id;
         // set any user-input fields, which will end up in the order item meta data (which can be displayed on the frontend)
         $fields = $voucher->get_user_input_voucher_fields();
         foreach ($fields as $field) {
             if (isset($_POST[$field['name']][$_product_id])) {
                 $cart_item_data['voucher_item_meta_data'][$field['name']] = $_POST[$field['name']][$_product_id];
             }
         }
         // add a random so that multiple of the same product can be added to the cart when "sold individually" is enabled
         $cart_item_data['voucher_random'] = uniqid('voucher_');
     }
     return $cart_item_data;
 }
 /**
  * Called when an order is updated from the admin, creates a new voucher if
  * a voucher item was added, and updates the voucher expiration and redeem
  * item meta.
  *
  * @since 1.2
  * @param int $post_id the post identifier
  * @param object $post the order post object
  *
  * @return array order item data to persist
  */
 public function process_shop_order_meta($post_id, $post)
 {
     // get the order
     $order = wc_get_order($post_id);
     $order_items = $order->get_items();
     // loop through any order items by id
     if (isset($_POST['order_item_id'])) {
         foreach ($_POST['order_item_id'] as $item_id) {
             $item_id = absint($item_id);
             if (!isset($order_items[$item_id]) || !$order_items[$item_id]) {
                 continue;
             }
             $order_item = $order_items[$item_id];
             $product_id = $order_item['variation_id'] ? $order_item['variation_id'] : $order_item['product_id'];
             $product = wc_get_product($product_id);
             // if we have a voucher product, but no voucher set for the order item, this is likely an item newly added from the admin, so create a default voucher
             if ($product && $product->is_downloadable() && WC_PDF_Product_Vouchers_Product::has_voucher($product) && (!isset($order_item['voucher_id']) || !$order_item['voucher_id'])) {
                 $voucher = WC_PDF_Product_Vouchers_Product::get_voucher($product);
                 $voucher_number = WC_PDF_Product_Vouchers_Voucher::generate_voucher_number();
                 wc_add_order_item_meta($item_id, '_voucher_image_id', $voucher->get_image_id());
                 wc_add_order_item_meta($item_id, '_voucher_id', $voucher->id);
                 wc_add_order_item_meta($item_id, '_voucher_redeem', array_pad(array(), $order_item['qty'], null));
                 // TODO: need to handle the order item quantity being changed from the admin
                 wc_add_order_item_meta($item_id, '_voucher_number', $voucher_number);
                 // if download permissions have already been granted, grant permission to the newly created voucher
                 if (isset($order->download_permissions_granted[0]) && 1 == $order->download_permissions_granted[0]) {
                     wc_downloadable_file_permission('wc_vouchers_' . $voucher_number, $product_id, $order);
                 }
             }
             if (isset($_POST['voucher_expiration'][$item_id])) {
                 wc_update_order_item_meta($item_id, '_voucher_expiration', $_POST['voucher_expiration'][$item_id]);
             }
             if (isset($_POST['voucher_redeem'][$item_id])) {
                 wc_update_order_item_meta($item_id, '_voucher_redeem', $_POST['voucher_redeem'][$item_id]);
             }
         }
     }
 }
 /**
  * Return our voucher file path as the download file
  *
  * @since 1.2
  * @param string $download_file_path the download file path
  * @param int $product the product
  * @param int $download_id downloadable file identifier
  *
  * @return string the download file path
  */
 public function voucher_file_download_path($download_file_path, $product, $download_id)
 {
     global $wpdb, $post;
     // if there is no download file path set, it means this might be an item voucher being requested
     if (!$download_file_path) {
         $order_id = null;
         if ($post && 'shop_order' == $post->post_type && $post->ID) {
             $order_id = $post->ID;
         }
         // are we being called from the context of the has_file() checks?
         if (!$order_id && (!isset($_GET['download_file']) || !isset($_GET['order']) || !isset($_GET['email']) || !isset($_GET['key']))) {
             if (WC_PDF_Product_Vouchers_Product::has_voucher($product)) {
                 return $download_id;
             } else {
                 // otherwise, non-voucher product, return the passed-in value
                 return $download_file_path;
             }
         }
         if (!$order_id) {
             // get the order id from the GET parameters when needed
             $order_key = urldecode($_GET['order']);
             $email = str_replace(' ', '+', urldecode($_GET['email']));
             $order_id = $wpdb->get_var($wpdb->prepare("\n\t\t\t\t\tSELECT order_id\n\t\t\t\t\tFROM {$wpdb->prefix}woocommerce_downloadable_product_permissions\n\t\t\t\t\tWHERE user_email = %s\n\t\t\t\t\tAND order_key = %s\n\t\t\t\t\tAND product_id = %s\n\t\t\t\t\tAND download_id = %s", $email, $order_key, isset($product->variation_id) ? $product->variation_id : $product->id, $download_id));
         }
         // get and return the path to the requested voucher file
         if ($order_id) {
             $order = wc_get_order($order_id);
             $voucher = WC_PDF_Product_Vouchers_Order::get_voucher_by_voucher_number($order, str_replace('wc_vouchers_', '', $download_id));
             if ($voucher && $voucher->file_exists($this->plugin->get_uploads_path())) {
                 $download_file_path = $voucher->get_voucher_full_filename($this->plugin->get_uploads_path());
                 if ('redirect' === get_option('woocommerce_file_download_method')) {
                     $download_file_path = $voucher->convert_path_to_url($file_path);
                 }
             }
         }
     }
     return $download_file_path;
 }