From ca082e16f13b1c0439af8c130ab6d813d7350649 Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Thu, 30 Apr 2015 17:15:19 +0200
Subject: [PATCH] make it a bit more generic

---
 assets/js/ordernumber-counter.js      |  2 +-
 woocommerce-advanced-ordernumbers.php | 78 +++++++++++++++------------
 2 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/assets/js/ordernumber-counter.js b/assets/js/ordernumber-counter.js
index 848ed6a..a098ba7 100644
--- a/assets/js/ordernumber-counter.js
+++ b/assets/js/ordernumber-counter.js
@@ -30,7 +30,7 @@ var ajaxEditCounter = function (btn, nrtype, ctr, value) {
 	var value = NaN;
 	var msgprefix = "";
 	while (isNaN (value) && (value != null)) {
-		value = prompt (String.Format (ajax_ordernumber.ORDERNUMBER_JS_EDITCOUNTER, msgprefix, counter.counter, counter.value)+ ajax_ordernumber.ajax_url, counter.value);
+		value = prompt (String.Format (ajax_ordernumber.ORDERNUMBER_JS_EDITCOUNTER, msgprefix, counter.counter, counter.value), counter.value);
 		if (value != null)
 			value = parseInt (value);
 		if (isNaN (value)) 
diff --git a/woocommerce-advanced-ordernumbers.php b/woocommerce-advanced-ordernumbers.php
index d5687f8..af39a82 100644
--- a/woocommerce-advanced-ordernumbers.php
+++ b/woocommerce-advanced-ordernumbers.php
@@ -14,9 +14,10 @@ WC tested up to: 2.3
 */
 
 /**
- * The structure of this plugin originally followed the tutorial, although much of the plugin has been rewritten since then:
+ * The structure of this plugin originally followed this tutorial, although much of the plugin has been rewritten since then:
  * http://www.yaconiello.com/blog/how-to-write-wordpress-plugin/
  * A lot of coding ideas were also taken directly from the way things are implemented in WooCommerce itself.
+ * The order number handling code itself comes straight from our general library, which is also used for VirtueMart and Magento.
  */
  
 if ( ! defined( 'ABSPATH' ) ) { 
@@ -29,7 +30,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 
 	if (!class_exists("OpenToolsOrdernumbers")) {
 		class OpenToolsOrdernumbers {
-			public $ordernumber_meta = "_order_number";
+			public $ordernumber_meta = "oton_number_";
 			public $ordernumber_new_placeholder = "[New Order]";
 			public $ordernumber_counter_prefix = 'ordernumber-counter-';
 			
@@ -64,7 +65,6 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				$plugin = plugin_basename(__FILE__); 
 				load_plugin_textdomain('opentools-ordernumbers', false, basename( dirname( __FILE__ ) ) . '/languages' );
 
-
 				// Init settings
 				$this->settings = array(
 					array(
@@ -131,7 +131,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				);
 				// Default options
 
-				add_option ('customize_ordernumber', '0');
+				add_option ('customize_ordernumber', 'no');
 				add_option ('ordernumber_format',    "#");
 				add_option ('ordernumber_global',    'no');
 				
@@ -165,8 +165,8 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'modify_order_column_sortkey' ), 9999 );
 
 				// When a new order is created, we immediately assign the order number:
-				add_action( 'wp_insert_post', array(&$this, 'check_create_ordernumber'), 10, 3);
-// 				add_action( 'save_post', array(&$this, 'check_create_ordernumber'), 10, 3);
+				add_action( 'wp_insert_post', array(&$this, 'check_assignNumber'), 10, 3);
+// 				add_action( 'save_post', array(&$this, 'check_assignNumber'), 10, 3);
 				// The filter to actually return the order number for the given order
 				add_filter ('woocommerce_order_number', array(&$this, 'get_ordernumber'), 10, 2/*<= Also get the order object! */);
 			}
@@ -333,6 +333,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			}
 
 			protected function create_replacements_row_html($name, $values = array(), $disabled = '') {
+				$escname = esc_attr($name);
 				$operator = (isset($values['conditionop'])?$values['conditionop']:'');
 				$operators = array(
 					'equals'       => '=', 
@@ -344,18 +345,19 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					'startswith'   => self::__('starts with'),
 					'endswith'     => self::__('ends with'),
 				);
+				// Wrap all output of the values with esc_html to prevent script injection attacks
 				$html  = '
 				<tr>
-					<td class="variables_ifvar"><input name="' . $name . '[conditionvar][]" value="' . (isset($values['conditionvar'])?$values['conditionvar']:'') . '" ' . $disabled . '/></td>
-					<td class="variables_ifop"      ><select name="' . $name . '[conditionop][]" ' . $disabled . '>';
+					<td class="variables_ifvar"><input name="' . $escname . '[conditionvar][]" value="' . (isset($values['conditionvar'])?esc_html($values['conditionvar']):'') . '" ' . esc_html($disabled) . '/></td>
+					<td class="variables_ifop"      ><select name="' . $escname . '[conditionop][]" ' . $disabled . '>';
 				foreach ($operators as $op => $opname) {
 					$html .= '		<option value="' . esc_attr($op) . '" ' . (($op === $operator)?'selected':'') . '>' . esc_html($opname) . '</option>';
 				}
-				$html .= '</td>
-					<td class="variables_ifval"   ><input name="' . $name . '[conditionval][]" value="' . (isset($values['conditionval'])?$values['conditionval']:'') . '" ' . $disabled . '/></td>
+				$html .= '</select></td>
+					<td class="variables_ifval"   ><input name="' . $escname . '[conditionval][]" value="' . (isset($values['conditionval'])?esc_html($values['conditionval']):'') . '" ' . esc_html($disabled) . '/></td>
 					<td class="variables_then">=></td>
-					<td class="variables_thenvar"><input name="' . $name . '[newvar][]"       value="' . (isset($values['newvar'])?$values['newvar']:'') .       '" ' . $disabled . '/></td>
-					<td class="variables_thenval"><input name="' . $name . '[newval][]"       value="' . (isset($values['newval'])?$values['newval']:'') .       '" ' . $disabled . '/></td>
+					<td class="variables_thenvar"><input name="' . $escname . '[newvar][]"       value="' . (isset($values['newvar'])?esc_html($values['newvar']):'') .       '" ' . esc_html($disabled) . '/></td>
+					<td class="variables_thenval"><input name="' . $escname . '[newval][]"       value="' . (isset($values['newval'])?esc_html($values['newval']):'') .       '" ' . esc_html($disabled) . '/></td>
 					<td class="sort"></td>
 					<td class="variables_settings"><img src="' . self::img_url( 'icon-16-delete.png' ) . '" class="ordernumber-replacement-deletebtn ordernumber-btn"></td>
 				</tr>';
@@ -521,7 +523,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			 * Handle the "Assign a new order number" action from the edit order page in the backend
 			 */
 			public function order_action_assign_new_ordernumber( $order ) {
-				$number = $this->create_ordernumber($order->id, $order, 'ordernumber');
+				$number = $this->assignNumber($order->id, $order, 'ordernumber');
 			}
 			
 			
@@ -530,7 +532,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			 * not only for orders, so we need to check explicitly. Also, this function will be called
 			 * for order updates, so we need to check the update argument, too.
 			 */
-			public function check_create_ordernumber($post_id, $post, $update) {
+			public function check_assignNumber($post_id, $post, $update) {
 				// Is the post really an order?
 				// Order numbers are only assigned to orders on creation, not when updating!
 				if ($post->post_type != 'shop_order') {
@@ -663,14 +665,12 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
     
 			protected function setupOrderReplacements (&$reps, $order, $nrtype) {
 				$reps["[orderid]"] = $order->id;
-				$reps["[ipaddress]"]   = $order->customer_ip_address;
 				
 				if ($nrtype != 'ordernumber') {
 					$reps["[ordernumber]"] = $order->get_order_number();
 				}
 				$reps["[orderstatus]"] = $order->get_status();
 				$reps["[currency]"]    = $order->get_order_currency();
-				$reps["[userid]"]      = $order->get_user_id();
 
 				$this->setupAddressReplacements($reps, "", $order, $nrtype);
 	
@@ -709,7 +709,12 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				$reps["[tags]"] = array_keys($tags);
 				$reps["[shippingclasses]"] = array_keys($shippingclasses);
 			}
-   
+
+			protected function setupUserReplacements (&$reps, $details, $nrtype) {
+				$reps["[ipaddress]"]   = $details->customer_ip_address;
+				$reps["[userid]"]      = $details->get_user_id();
+			}
+
 			protected function setupShippingReplacements(&$reps, $order, $nrtype) {
 // 				$reps["[shippingmethod]"] = $order->getShippingMethod();
 			}
@@ -718,13 +723,18 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				$reps["[invoiceid]"] = $invoice->getId();
 			}*/
 
-			protected function setupReplacements($nrtype, $order) {
+			protected function setupThirdPartyReplacements (&$reps, $details, $nrtype) {
+				$reps = apply_filters( 'opentools_ordernumber_replacements', $reps, $details, $nrtype);
+			}
+			
+			protected function setupReplacements($nrtype, $details) {
 				$reps = array();
-				$this->setupDateTimeReplacements($reps, $order, $nrtype);
-				$this->setupStoreReplacements($reps, $order, $nrtype);
-				$this->setupOrderReplacements($reps, $order, $nrtype);
-				$this->setupShippingReplacements($reps, $order, $nrtype);
-				$reps = apply_filters( 'opentools_ordernumber_replacements', $reps, $order, $nrtype);
+				$this->setupDateTimeReplacements($reps, $details, $nrtype);
+				$this->setupStoreReplacements($reps, $details, $nrtype);
+				$this->setupOrderReplacements($reps, $details, $nrtype);
+				$this->setupUserReplacements($reps, $details, $nrtype);
+				$this->setupShippingReplacements($reps, $details, $nrtype);
+				$this->setupThirdPartyReplacements($reps, $details, $nrtype);
 				return $reps;
 			}
 
@@ -754,6 +764,8 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					if ($found) {
 						$condval = $c['conditionval'];
 						switch ($op) {
+							case 'nocondition':
+									$match = true; break;
 							case 'equals': 
 									$match = ($compareval == $condval); break;
 							case 'contains':
@@ -866,8 +878,8 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				return $number;
 			}
 			
-			function create_ordernumber($orderid, $order, $type='ordernumber') {
-				if (get_option('customize_'.$type, 'false')) {
+			function assignNumber($orderid, $order, $type='ordernumber') {
+				if (get_option('customize_'.$type, 'no')!='no') {
 					$fmt     = get_option ($type.'_format',  "#");
 					$ctrsettings = array(
 						"${type}_format"  => '',
@@ -880,7 +892,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					$customvars = get_option ('ordernumber_variables',   array());
 
 					$number = $this->createNumber ($fmt, $type, $order, $customvars, $ctrsettings);
-					update_post_meta( $orderid, $this->ordernumber_meta, $number );
+					update_post_meta( $orderid, $this->ordernumber_meta.$type, $number );
 					return $number;
 				} else {
 					return $orderid;
@@ -893,29 +905,29 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			function assign_new_ordernumber($orderid, $order, $update=true) {
 				if ((!$update) /*&& ($order->post_status == 'auto-draft')*/) {
 					// New order => assign placeholder, which will later be overwritten the real order number
-					update_post_meta( $orderid, $this->ordernumber_meta, $this->ordernumber_new_placeholder );
+					update_post_meta( $orderid, $this->ordernumber_meta.'ordernumber', $this->ordernumber_new_placeholder );
 				}
 				// If we do not have an order (yet), we cannot proceed. But we probably have created the 
 				// ordernumber placeholder for that post, so this function has done its job and we can return
 				if (!$order instanceof WC_Order) {
 					return;
 				}
-				$number = get_post_meta( $orderid, $this->ordernumber_meta, 'true');
+				$number = get_post_meta( $orderid, $this->ordernumber_meta.'ordernumber', 'true');
 				if ($number == $this->ordernumber_new_placeholder && $order->post_status != 'auto-draft') {
-					$number = $this->create_ordernumber($orderid, $order, 'ordernumber');
+					$number = $this->assignNumber($orderid, $order, 'ordernumber');
 					// Assign a new number
 				}
 				return $number;
 			}
 
 			/** 
-			 * The hook to customize order numbers (requests the order number from the database; creates a new ordernumber if no entry exists in the database)
+			 * The generic function to retrieve a particular number
 			 */
-			function get_ordernumber($orderid, $order) {
-				$stored_number = get_post_meta( $orderid, $this->ordernumber_meta, 'true');
+			function get_number($orderid, $order, $type = 'ordernumber') {
+				$stored_number = get_post_meta( $orderid, $this->ordernumber_meta.$type, 'true');
 				if ($stored_number == $this->ordernumber_new_placeholder) {
 					// Check whether the order was now really created => create order number now
-					return $this->assign_new_ordernumber($orderid, $order);
+					return $this->assign_new_ordernumber($orderid, $order, $type);
 				} elseif (!empty($stored_number)) {
 					// Order number already exists => simply return it
 					return $stored_number;
-- 
GitLab