<?php /** * This is the actual ordernumber plugin class for WooCommerce. * Copyright (C) 2015 Reinhold Kainhofer, Open Tools * Author: Open Tools, Reinhold Kainhofer * Author URI: http://open-tools.net * License: GPL2+ */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } if (!class_exists( 'OpenToolsOrdernumbersBasic' )) require_once (dirname(__FILE__) . '/ordernumbers_woocommerce_basic.php'); class OpenToolsOrdernumbers extends OpenToolsOrdernumbersBasic { /** * Construct the plugin object */ public function __construct($basename) { parent::__construct($basename); $this->is_advanced = true; $this->helper->registerCallback('setupStoreReplacements', array($this, 'setupStoreReplacements')); $this->helper->registerCallback('setupOrderReplacements', array($this, 'setupOrderReplacements')); $this->helper->registerCallback('setupUserReplacements', array($this, 'setupUserReplacements')); $this->helper->registerCallback('setupShippingReplacements', array($this, 'setupShippingReplacements')); $this->helper->registerCallback('setupThirdPartyReplacements', array($this, 'setupThirdPartyReplacements')); } /** * Override the initializeBasicSettings method, which restricts some functionality in the basic plugin. */ protected function initializeBasicSettings() {} /** * Install all neccessary filters and actions for this plugin */ protected function initializeHooks() { parent::initializeHooks(); // Custom table widget for custom variable definitions: Hooks for creating and storing values add_action( 'woocommerce_admin_field_ordernumber_variables', array( $this, 'admin_field_variables' ) ); add_action( 'pre_update_option_ordernumber_variables', array( $this, 'update_option_variables')); // Install hooks for third-party plugin support: $this->thirdparty_wpo_wcpdf_init(); } protected function initializeSettingsGeneral() { // Remove the NAG screen of the basic version return array(); } /** * Return the tooltip for the number format settings textinput (the two plugin versions have different features!) */ protected function getNumberFormatSettingsLabel() { return $this->helper->__( 'The format for the order numbers (variables can be entered as [...], the counter is indicated by the #). To use a different counter name than displayed, put the custom counter name after a |, e.g. "[year]-[month]/#|[year]" to use the month in the order number, but reset the counter only yearly. Advanced settings for the counter can be added as [#####:start/step], e.g. [#:100] to start new counters at 100, or [#/5] to increment the counter by 5. The number of # in the format determine how many digits are shown at least, e.g. [########] will always show at least 8 digits for the counter, e.g. 00000014.'); } protected function addGlobalCounterSettings($settings) { $settings[] = array( 'title' => $this->helper->__( 'Use global counter'), 'desc' => $this->helper->__( 'A global counter never resets. Non-global counters run within each number format and reset whenever any variable changes.'), 'id' => 'ordernumber_global', 'type' => 'checkbox', 'default' => 'no', ); return $settings; } protected function initializeSettingsOther() { return array_merge( $this->initializeSettingsInvoiceNumbers(), $this->initializeSettingsReplacements() ); } protected function initializeSettingsInvoiceNumbers() { $settings = array( /** * Invoice number settings */ array( 'name' => $this->helper->__( 'Advanced Invoice Numbers'), 'desc' => $this->helper->__('This plugin currently supports modifying the invoice number formats of the following invoicing plugins: <a href="https://wordpress.org/plugins/woocommerce-pdf-invoices-packing-slips/">WooCommerce PDF Invoices & Packing Slips</a>'), 'type' => 'title', 'id' => 'invoice_options' ), array( 'name' => $this->helper->__( 'Customize Invoice Numbers'), 'desc' => $this->helper->__( 'Check to use custom invoice numbers rather than the default format of your invoicing plugin.'), 'id' => 'customize_invoice', 'type' => 'checkbox', 'default' => 'no' ), array( 'title' => $this->helper->__( 'Invoice number format'), 'desc' => $this->helper->__( 'The format for the invoice numbers (variables can be entered as [...], the counter is indicated by the #). To use a different counter name than displayed, put the custom counter name after a |, e.g. "[year]-[month]/#|[year]" to use the month in the invoice number, but reset the counter only yearly. Advanced settings for the counter can be added as [#####:start/step], e.g. [#:100] to start new counters at 100, or [#/5] to increment the counter by 5. The number of # in the format determine how many digits are shown at least, e.g. [########] will always show at least 8 digits for the counter, e.g. 00000014.'), 'desc_tip' => true, 'id' => 'invoice_format', 'default' => '#', 'type' => 'text', 'css' => 'width: 100%', ), array( 'title' => $this->helper->__( 'Use global counter'), 'desc' => $this->helper->__( 'A global counter never resets. Non-global counters run within each number format and reset whenever any variable changes.'), 'id' => 'invoice_global', 'type' => 'checkbox', 'default' => 'no', ), array( 'name' => $this->helper->__( 'All invoice number counters'), 'desc' => $this->helper->__( 'View and modify the current counter values. The counter value is the value used for the previous number. All changes are immediately applied!'), 'desc_tip' => true, 'id' => 'ordernumber_counters', 'type' => 'ordernumber_counters', 'nrtype' => 'invoice', ), array( 'type' => 'sectionend', 'id' => 'invoice_options' ) ); add_option ('customize_invoice', 'no'); add_option ('invoice_format', "#"); add_option ('invoice_global', 'no'); return $settings; } protected function initializeSettingsReplacements() { $settings = array( array( 'name' => $this->helper->__( 'Custom Variables'), 'desc' => $this->helper->__( 'Define your own (conditional) variables for use in the number formats'), 'type' => 'title', 'id' => 'ordernumber_variables' ), array( 'id' => 'ordernumber_variables', 'type' => 'ordernumber_variables', ), array( 'type' => 'sectionend', 'id' => 'ordernumber_variables' ) ); add_option ('ordernumber_variables', array()); return $settings; } /** * Render the Custom Variables configuration table */ public function admin_field_variables($settings) { $variables = get_option( $settings['id'], array() ); if (!is_array($variables)) { $variables = array(); } ?> <tr valign="top"> <td class="forminp forminp-<?php echo sanitize_title( $settings['type'] ) ?>" colspan="2"> <?php print $this->helper->custom_variables_create_table($settings['id'], $variables); ?> </td> </tr> <?php } /** * Store the variable replacements array into the options. Need to transpose the array before we can store it into the options... * This filter is called directly before the option is saved. */ public function update_option_variables ($value) { return OrdernumberHelper::transposeCustomVariables($value); } /** *********************************************************** * * REPLACEMENT FUNCTIONS * **************************************************************/ public function setupAddressReplacements(&$reps, $prefix, $address, $nrtype) { $reps["[email]"] = $address->billing_email; $reps["[firstname]"] = $address->billing_first_name; $reps["[lastname]"] = $address->billing_last_name; $reps["[company]"] = $address->billing_company; $reps["[zip]"] = $address->billing_postcode; $reps["[postcode]"] = $address->billing_postcode; $reps["[city]"] = $address->billing_city; $country = $address->billing_country; $state = $address->billing_state; $allcountries = WC()->countries->get_countries(); $states = WC()->countries->get_states($country); $reps["[country]"] = $country; $reps["[countryname]"] = ( isset( $allcountries[ $country ] ) ) ? $allcountries[ $country ] : $country; $reps["[state]"] = $state; $reps["[statename]"] = ( $country && $state && isset( $states[ $country ][ $state ] ) ) ? $states[ $country ][ $state ] : $state; } public function setupStoreReplacements (&$reps, $order, $nrtype) { } public function setupOrderReplacements (&$reps, $order, $nrtype) { $reps["[orderid]"] = $order->id; if ($nrtype != 'ordernumber') { $reps["[ordernumber]"] = $order->get_order_number(); } $reps["[orderstatus]"] = $order->get_status(); $reps["[currency]"] = $order->get_order_currency(); $this->setupAddressReplacements($reps, "", $order, $nrtype); $reps["[articles]"] = $order->get_item_count(); // $reps["[downloadpermitted]"] = $order->is_download_permitted(); // $reps["[hasdownloads]"] = $order->has_downloadable_item(); // $reps["[coupons]"] = $order->get_used_coupons(); $reps["[ordertotal]"] = $order->get_total(); $reps["[amount]"] = $order->get_total(); $reps["[ordersubtotal]"] = $order->get_subtotal(); $reps["[totaltax]"] = $order->get_total_tax(); $reps["[totalshipping]"] = $order->get_total_shipping(); // List-valued properties for custom variable checks: // TODO: Also implement variable for: // - Shipping needed // - Downloads available $lineitems = $order->get_items(); $skus = array(); $categories = array(); $tags = array(); $shippingclasses = array(); foreach ($lineitems as $l) { $p = $order->get_product_from_item($l); $skus[$p->get_sku()] = 1; foreach (wc_get_product_terms( $p->id, 'product_cat') as $c) { $categories[$c->slug] = 1; } foreach (wc_get_product_terms( $p->id, 'product_tag') as $c) { $tags[$c->slug] = 1; } $shippingclasses[$p->get_shipping_class()] = 1; } $reps["[skus]"] = array_keys($skus); $reps["[categories]"] = array_keys($categories); $reps["[tags]"] = array_keys($tags); $reps["[shippingclasses]"] = array_keys($shippingclasses); } public function setupUserReplacements (&$reps, $details, $nrtype) { $reps["[ipaddress]"] = $details->customer_ip_address; $reps["[userid]"] = $details->get_user_id(); } public function setupShippingReplacements(&$reps, $order, $nrtype) { // $reps["[shippingmethod]"] = $order->getShippingMethod(); } /*public function setupInvoiceReplacements (&$reps, $invoice, $order, $nrtype) { $reps["[invoiceid]"] = $invoice->getId(); }*/ public function setupThirdPartyReplacements (&$reps, $details, $nrtype) { $reps = apply_filters( 'opentools_ordernumber_replacements', $reps, $details, $nrtype); } /** ************************************************************ * Support for WPO WooCommerce PDF Invoices and Packaging Slips ** ************************************************************ * * - Invoice numbers are stored in the _wcpdf_invoice_number post meta * - the filter wpo_wcpdf_invoice_number($invoice_number, $order_number, $order_id, $order_data) is called * to format the (existing) invoice number retrieved from that post meta * - The action wpo_wcpdf_process_template_order($template_type, $order_id) is called right before * the invoice is created. There we can already set the _wcpdf_invoice_number post meta with our own value */ /** * Initialize support for WPO WooCommerce PDF Invoices and Packaging Slips */ protected function thirdparty_wpo_wcpdf_init() { // TODO: Wheck whether the woocommerce-pdf-invoices-packing-slips plugin is installed at all add_filter ('wpo_wcpdf_invoice_number', array($this, 'thirdparty_wpo_wcpdf_invoice_number'), 30, 4); add_action ('wpo_wcpdf_process_template_order', array($this, 'thirdparty_wpo_wcpdf_create_number'), 10, 2); // Disable the invoice number-related controls in the config of the other plugin add_action ('woocommerce_page_wpo_wcpdf_options_page', array($this, 'thirdparty_wpo_wcpdf_remove_options')); } /** * Support for WPO WooCommere PDF Invoices and Packaging Slips * Filter to return the invoice number => simply return the first argument unchanged (was already * created in the correct format, no need to format it now again) */ function thirdparty_wpo_wcpdf_invoice_number($invoice_number, $order_number, $order_id, $order_data) { $nr = $this->get_number($order_id, $order_data, 'invoice'); if ($nr == $order_id) { // No number was found, so the default is the order id => reset to invoice number return $invoice_number; } else { return $nr; } } /** * The action to actually create the number and store it as post meta with the order */ function thirdparty_wpo_wcpdf_create_number($type, $orderid) { if ($type=='invoice' && (get_option('customize_'.$type, 'no')!='no') ) { $_of = new WC_Order_Factory(); $order = $_of->get_order($orderid); $number = $this->get_or_create_number($orderid, $order, $type); // TODO: Store the invoice number counter in _wcpdf_invoice_number and the custom invoice // number in the opentools meta, because the plugin assumes the number to be numeric... update_post_meta( $orderid, '_wcpdf_invoice_number', $number ); } } /** * The action that is called for the WPO WCPDF invoice plugin only, when the options page is loaded. * If this plugin is enabled and invoice numbers are configured, we simply remove all invoice number-specific * settings, because this plugin will be responsible.... */ function thirdparty_wpo_wcpdf_remove_options() { global $wp_settings_fields; if (get_option('customize_invoice', 'no')!='no') { $wp_settings_fields['wpo_wcpdf_template_settings']['invoice']['display_number']['title'] = $this->helper->__('Display invoice number'); $wp_settings_fields['wpo_wcpdf_template_settings']['invoice']['display_number']['args']['description'] = $this->helper->__('The <a href="admin.php?page=wc-settings&tab=checkout§ion=ordernumber">Open Tools Ordernumber plugin</a> has invoice numbers enabled and will generate invoice numbers for this plugin.' ); unset($wp_settings_fields['wpo_wcpdf_template_settings']['invoice']['next_invoice_number']); unset($wp_settings_fields['wpo_wcpdf_template_settings']['invoice']['invoice_number_formatting']); } else { $wp_settings_fields['wpo_wcpdf_template_settings']['invoice']['display_number']['args']['description'] = $this->helper->__('To let the Open Tools ordernumber plugin create invoice numbers with your desired format, please enable invoices in <a href="admin.php?page=wc-settings&tab=checkout§ion=ordernumber">that plugin\'s configuration page</a>.' ); } } }