diff --git a/woocommerce-advanced-ordernumbers.php b/woocommerce-advanced-ordernumbers.php
index ebeff04f419c16e8b1c686f091dfd9dda6986e99..062a7d58ab2968c20e21541cf8365d54b851ffc2 100644
--- a/woocommerce-advanced-ordernumbers.php
+++ b/woocommerce-advanced-ordernumbers.php
@@ -28,7 +28,6 @@ if ( ! defined( 'ABSPATH' ) ) {
 if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
     // Put your plugin code here
     // Load the language files
-	load_plugin_textdomain('opentools-ordernumbers', false, basename( dirname( __FILE__ ) ) . '/languages' );
 
 	if (!class_exists("OpenToolsOrdernumbers")) {
 		class OpenToolsOrdernumbers {
@@ -36,65 +35,89 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			public $ordernumber_new_placeholder = "[New Order]";
 			public $ordernumber_counter_prefix = 'ordernumber-counter-';
 			
+			
+			/**
+			 * STATIC HELPER FUNCTIONS, WooCommerce-specific
+			 */
+			public static function __($string) {
+				return __($string, 'opentools-advanced-ordernumbers');
+			}
+			public static function rel_url($file) {
+				return plugins_url($file, __FILE__);
+			}
+			public static function img_url($img) {
+				return self::rel_url('assets/images/'.$img );
+			}
+			public static function css_url($css) {
+				return self::rel_url('assets/css/'.$css );
+			}
+			public static function js_url($js) {
+				return self::rel_url('assets/js/'.$js );
+			}
+			
+			
+			
+			
 			/**
 			 * Construct the plugin object
 			 */
 			public function __construct()
 			{
 				$plugin = plugin_basename(__FILE__); 
+				load_plugin_textdomain('opentools-ordernumbers', false, basename( dirname( __FILE__ ) ) . '/languages' );
 
 
 				// Init settings
 				$this->settings = array(
 					array(
-						'name' 		=> __( 'Advanced Order Numbers', 'woocommerce-advanced-ordernumbers' ),
-						'desc'		=> __( 'Configure the format and the counters of the order numbers in WooCommerce.', 'woocommerce-advanced-ordernumbers' ),
+						'name' 		=> self::__( 'Advanced Order Numbers'),
+						'desc'		=> self::__( 'Configure the format and the counters of the order numbers in WooCommerce.'),
 						'type' 		=> 'title',
 						'id' 		=> 'ordernumber_options'
 					),
 
 					array(
-						'name' 		=> __( 'Customize Order Numbers', 'woocommerce-advanced-ordernumbers' ),
-						'desc' 		=> __( 'Check to use custom order numbers rather than the default wordpress post ID.', 'woocommerce-advanced-ordernumbers' ),
+						'name' 		=> self::__( 'Customize Order Numbers'),
+						'desc' 		=> self::__( 'Check to use custom order numbers rather than the default wordpress post ID.'),
 						'id' 		=> 'customize_ordernumber',
 						'type' 		=> 'checkbox',
 						'default'	=> 'no'
 					),
 					array(
-						'title'		=> __( 'Order number format', 'woocommerce-advanced-ordernumbers' ),
-						'desc' 		=> __( '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.', 'woocommerce-advanced-ordernumbers' ),
+						'title'		=> self::__( 'Order number format'),
+						'desc' 		=> self::__( '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.'),
 						'desc_tip'	=> true,
 						'id' 		=> 'ordernumber_format',
 						'default'	=> '#',
 						'type' 		=> 'text',
 					),
 					array(
-						'title'		=> __( 'Use global counter', 'woocommerce-advanced-ordernumbers' ),
-						'desc' 		=> __( 'A global counter is independent of the number format and will never reset. A non-global counter runs within the number format and will start from the inital value whenever any of the variables used in the format changes (to be precise: a new counter will be used, so it is possible to have multiple counters running in parallel).', 'woocommerce-advanced-ordernumbers' ),
+						'title'		=> self::__( 'Use global counter'),
+						'desc' 		=> self::__( 'A global counter is independent of the number format and will never reset. A non-global counter runs within the number format and will start from the inital value whenever any of the variables used in the format changes (to be precise: a new counter will be used, so it is possible to have multiple counters running in parallel).'),
 						'desc_tip'	=> true,
 						'id' 		=> 'ordernumber_global',
 						'type' 		=> 'checkbox',
 						'default'	=> 'no'
 					),
 					array(
-						'title' 	=> __( 'Counter Digits', 'woocommerce-advanced-ordernumbers' ),
-						'desc' 		=> __( 'Minimum number of digits for the number', 'woocommerce-advanced-ordernumbers' ),
+						'title' 	=> self::__( 'Counter Digits'),
+						'desc' 		=> self::__( 'Minimum number of digits for the number'),
 						'desc_tip'	=> true,
 						'id' 		=> 'ordernumber_padding',
 						'type' 		=> 'number',
 						'default'	=> '0'
 					),
 					array(
-						'title' 	=> __( 'Counter Start', 'woocommerce-advanced-ordernumbers' ),
-						'desc' 		=> __( 'Start value for each new counter', 'woocommerce-advanced-ordernumbers' ),
+						'title' 	=> self::__( 'Counter Start'),
+						'desc' 		=> self::__( 'Start value for each new counter'),
 						'desc_tip'	=> true,
 						'id' 		=> 'ordernumber_start',
 						'type' 		=> 'number',
 						'default'	=> '1'
 					),
 					array(
-						'title'	=> __( 'Counter step', 'woocommerce-advanced-ordernumbers' ),
-						'desc' 		=> __( 'By how much the counter will be increased after each order. Typically 1.', 'woocommerce-advanced-ordernumbers' ),
+						'title'		=> self::__( 'Counter step'),
+						'desc' 		=> self::__( 'By how much the counter will be increased after each order. Typically 1.'),
 						'desc_tip'	=> true,
 						'id' 		=> 'ordernumber_step',
 						'type' 		=> 'number',
@@ -105,27 +128,25 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					// TODO: customize order password, and other numbers!
 
 					array(
-						'name' 		=> __( 'Custom Variables', 'woocommerce-advanced-ordernumbers' ),
-						'desc'		=> __( 'Define your own (conditional) variables for use in the number formats', 'woocommerce-advanced-ordernumbers' ),
+						'name' 		=> self::__( 'Custom Variables'),
+						'desc'		=> self::__( 'Define your own (conditional) variables for use in the number formats'),
 						'type' 		=> 'title',
 						'id' 		=> 'ordernumber_variables'
 					),
 					array(
-// 						'title'		=> __( 'Custom ', 'woocommerce-advanced-ordernumbers' ),
-// 						'desc' 		=> __( '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.', 'woocommerce-advanced-ordernumbers' ),
 						'id' 		=> 'ordernumber_variables',
 						'type' 		=> 'ordernumber_variables',
 					),
 					array( 'type' => 'sectionend', 'id' => 'ordernumber_variables' ),
 
 					array(
-						'name' 		=> __( 'Current Counters', 'woocommerce-advanced-ordernumbers' ),
+						'name' 		=> self::__( 'Current Counters'),
 						'type' 		=> 'title',
 						'id' 		=> 'ordernumber_counters'
 					),
 					array(
-						'name' 		=> __( 'All Ordernumber Counters', 'woocommerce-advanced-ordernumbers' ),
-						'desc'		=> __( 'View and modify the current counter values. The counter value is the value used for the previous number. All changes are immediately applied!', 'woocommerce-advanced-ordernumbers' ),
+						'name' 		=> self::__( 'All Ordernumber Counters'),
+						'desc'		=> self::__( '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',
@@ -190,7 +211,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				foreach ($sections as $sec => $name ) {
 					$newsections[$sec] = $name;
 					if ($sec == '') {
-						$newsections['ordernumber'] = __( 'Order Numbers', 'woocommerce-advanced-ordernumbers');
+						$newsections['ordernumber'] = self::__('Order Numbers');
 					}
 				}
 				return $newsections;
@@ -216,10 +237,10 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			 * Print the CSS for the counter values and counter variables tables to the page header in the WC backend admin setting page
 			 */
 			public function print_admin_styles () {
-				wp_register_style ( 'ordernumber-counter-style',  plugins_url('assets/css/ordernumber-counter.css', __FILE__) );
+				wp_register_style ( 'ordernumber-counter-style',  self::css_url('ordernumber-counter.css') );
 				wp_enqueue_style('ordernumber-counter-style');
 
-				wp_register_style ( 'ordernumber-variables-style',  plugins_url('assets/css/ordernumber-variables.css', __FILE__) );
+				wp_register_style ( 'ordernumber-variables-style',  self::css_url('ordernumber-variables.css') );
 				wp_enqueue_style('ordernumber-variables-style');
 			}
 			/** 
@@ -227,29 +248,29 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			 */
 			public function print_admin_scripts() {
 			
-				wp_register_script( 'ordernumber-counter-script', plugins_url( 'assets/js/ordernumber-counter.js',  __FILE__), array('jquery') );
+				wp_register_script( 'ordernumber-counter-script', self::js_url( 'ordernumber-counter.js',  __FILE__), array('jquery') );
 				wp_enqueue_script( 'ordernumber-counter-script');
 				
 				// Handle the translations:
 				$localizations = array( 'ajax_url' => admin_url( 'admin-ajax.php' ) );
 				
-				$localizations['ORDERNUMBER_JS_JSONERROR'] = __("Error reading response from server:");
-				$localizations['ORDERNUMBER_JS_NOT_AUTHORIZED'] = __("You are not authorized to modify order number counters.");
-				$localizations['ORDERNUMBER_JS_NEWCOUNTER'] = __("Please enter the format/name of the new counter:");
-				$localizations['ORDERNUMBER_JS_ADD_FAILED'] = __("Failed adding counter {0}");
-				$localizations['ORDERNUMBER_JS_INVALID_COUNTERVALUE'] = __("You entered an invalid value for the counter.\n\n");
+				$localizations['ORDERNUMBER_JS_JSONERROR'] = self::__("Error reading response from server:");
+				$localizations['ORDERNUMBER_JS_NOT_AUTHORIZED'] = self::__("You are not authorized to modify order number counters.");
+				$localizations['ORDERNUMBER_JS_NEWCOUNTER'] = self::__("Please enter the format/name of the new counter:");
+				$localizations['ORDERNUMBER_JS_ADD_FAILED'] = self::__("Failed adding counter {0}");
+				$localizations['ORDERNUMBER_JS_INVALID_COUNTERVALUE'] = self::__("You entered an invalid value for the counter.\n\n");
 				
-				$localizations['ORDERNUMBER_JS_EDITCOUNTER'] = __("{0}Please enter the new value for the counter '{1}' (current value: {2}):");
-				$localizations['ORDERNUMBER_JS_MODIFY_FAILED'] = __("Failed modifying counter {0}");
-				$localizations['ORDERNUMBER_JS_DELETECOUNTER'] = __("Really delete counter '{0}' with value '{1}'?");
-				$localizations['ORDERNUMBER_JS_DELETE_FAILED'] = __("Failed deleting counter {0}");
+				$localizations['ORDERNUMBER_JS_EDITCOUNTER'] = self::__("{0}Please enter the new value for the counter '{1}' (current value: {2}):");
+				$localizations['ORDERNUMBER_JS_MODIFY_FAILED'] = self::__("Failed modifying counter {0}");
+				$localizations['ORDERNUMBER_JS_DELETECOUNTER'] = self::__("Really delete counter '{0}' with value '{1}'?");
+				$localizations['ORDERNUMBER_JS_DELETE_FAILED'] = self::__("Failed deleting counter {0}");
 
 				// in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.we_value
 				wp_localize_script( 'ordernumber-counter-script', 'ajax_ordernumber', $localizations );
 
 
 
-				wp_register_script( 'ordernumber-variables-script', plugins_url( 'assets/js/ordernumber-variables.js',  __FILE__), array('jquery') );
+				wp_register_script( 'ordernumber-variables-script', self::js_url( 'ordernumber-variables.js'), array('jquery') );
 				wp_enqueue_script( 'ordernumber-variables-script');
 			}
 
@@ -260,32 +281,35 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				$variables = get_option( $settings['id'], array() );
 				if (!is_array($variables)) {
 					$variables = array();
-				}
-// echo "<pre>Admin field " . print_r($settings['id'],1) . " has value: " . print_r($variables, 1) . "</pre>";
-
-				// Description handling
-				$field_description = WC_Admin_Settings::get_field_description( $settings );
-				extract( $field_description );
-				?>
-
+				} ?>
 		<tr valign="top">
 		    <td class="forminp forminp-<?php echo sanitize_title( $settings['type'] ) ?>" colspan="2">
+				<?php
+					print $this->customvar_admin_table($settings['id'], $variables);
+				?>
+			</td>
+		</tr> 
+		<?php
+			}
+			
+			protected function customvar_admin_table($id, $variables) { ?>
+			
 				<table id="ordernumber_variables_template" style="display:none">
-					<?php echo $this->create_replacements_row_html($settings['id'], array(), 'disabled'); ?>
+					<?php echo $this->create_replacements_row_html($id, array(), 'disabled'); ?>
 				</table>
 
 				<table id="ordernumber_variables" class="ordernumber_variables widefat wc_input_table sortable" cellspacing="0">
 					<?php
-						$columns = apply_filters( 'woocommerce_ordernumber_variables_columns', array(
-							'variables_ifvar'    => __( 'If variable ...', 'woocommerce-advanced-ordernumbers' ),
+						$columns = array(
+							'variables_ifvar'    => self::__( 'If variable ...'),
 							'variables_ifop'     => '',
-							'variables_ifval'    => __( 'Value', 'woocommerce-advanced-ordernumbers' ),
-							'variables_then'     => __( '', 'woocommerce-advanced-ordernumbers' ),
-							'variables_thenvar'  => __( 'Set variable ...', 'woocommerce-advanced-ordernumbers' ),
-							'variables_thenval'  => __( 'to value ...', 'woocommerce-advanced-ordernumbers' ),
+							'variables_ifval'    => self::__( 'Value'),
+							'variables_then'     => self::__( ''),
+							'variables_thenvar'  => self::__( 'Set variable ...'),
+							'variables_thenval'  => self::__( 'to value ...'),
 							'sort'     => '&nbsp;',
 							'variables_settings' => '',
-						) );
+						);
 					?>
 					<thead>
 						<tr>
@@ -297,8 +321,8 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 						</tr>
 						<tr id = "ordernumber-replacements-empty-row" class="oton-empty-row-notice <?php echo (empty($variables))?'':'rowhidden'; ?>">
 							<td class="oton-empty-row-notice" colspan="8">
-								<em> <?php echo __('No custom variables have been defined.', 'woocommerce-advanced-ordernumbers'); ?></em>
-								<input type="hidden" name="<?php echo $settings['id']; ?>" value="" <?php echo (empty($variables))?'':'disabled'; ?>>
+								<em> <?php echo self::__('No custom variables have been defined.'); ?></em>
+								<input type="hidden" name="<?php echo $id; ?>" value="" <?php echo (empty($variables))?'':'disabled'; ?>>
 							</td>
 						</tr>
 					</thead>
@@ -313,36 +337,34 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					<tbody>
 						<?php
 						foreach ($variables as $var) {
-							echo $this->create_replacements_row_html($settings['id'], $var);
+							echo $this->create_replacements_row_html($id, $var);
 						} ?>
 					</tbody>
 					<tfoot>
 						<tr class='addreplacement_row'>
 							<td colspan=8 class='variable_add'>
 								<div class='ordernumber-variables-addbtn ordernumber-btn' onClick="ordernumberVariablesAddRow('ordernumber_variables_template', 'ordernumber_variables')">
-									<div class='ordernumber-ajax-loading'><img src='<?php echo plugins_url( 'assets/images/icon-16-new.png', __FILE__ ); ?>' class='ordernumber-counter-addbtn' /></div>
-									<?php _e('Add new custom variable', 'woocommerce-advanced-ordernumbers'); ?>
+									<div class='ordernumber-ajax-loading'><img src='<?php echo self::img_url( 'icon-16-new.png' ); ?>' class='ordernumber-counter-addbtn' /></div>
+									<?php _e('Add new custom variable'); ?>
 								</div>
 							</td>
 						</tr>
 					</tfoot>
 				</table>
-			</td>
-		</tr> 
-		<?php
+				<?php
 			}
 
 			protected function create_replacements_row_html($name, $values = array(), $disabled = '') {
 				$operator = (isset($values['conditionop'])?$values['conditionop']:'');
 				$operators = array(
 					'equals'       => '=', 
-					'contains'     => __('contains', 'woocommerce-advanced-ordernumbers'), 
+					'contains'     => self::__('contains'), 
 					'smaller'      => '<',
 					'smallerequal' => '<=',
 					'larger'       => '>',
 					'largerequal'  => '>=', 
-					'startswith'   => __('starts with', 'woocommerce-advanced-ordernumbers'),
-					'endswith'     => __('ends with', 'woocommerce-advanced-ordernumbers'),
+					'startswith'   => self::__('starts with'),
+					'endswith'     => self::__('ends with'),
 				);
 				$html  = '
 				<tr>
@@ -357,7 +379,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					<td class="oton-replacement-variable"><input name="' . $name . '[newvar][]"       value="' . (isset($values['newvar'])?$values['newvar']:'') .       '" ' . $disabled . '/></td>
 					<td class="oton-replacement-newvalue"><input name="' . $name . '[newval][]"       value="' . (isset($values['newval'])?$values['newval']:'') .       '" ' . $disabled . '/></td>
 					<td class="sort">&nbsp;</td>
-					<td><img src="' . plugins_url( 'assets/images/icon-16-delete.png', __FILE__ ) . '" class="ordernumber-replacement-deletebtn ordernumber-btn"></td>
+					<td><img src="' . self::img_url( 'icon-16-delete.png' ) . '" class="ordernumber-replacement-deletebtn ordernumber-btn"></td>
 				</tr>';
 				return $html;
 			}
@@ -416,13 +438,13 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				<?php echo $tooltip_html; ?>
 			</th>
 		    <td class="forminp forminp-<?php echo sanitize_title( $settings['type'] ) ?>">
-				<img src='<?php echo plugins_url( 'assets/images/loading.gif', __FILE__ ); ?>' class='wc-ordernumber-loading' style="display: none; position: absolute; top: 2px; left: 0px; z-index: 9999;"/>
+				<img src='<?php echo self::img_url( 'loading.gif' ); ?>' class='wc-ordernumber-loading' style="display: none; position: absolute; top: 2px; left: 0px; z-index: 9999;"/>
 				<table class="wc_ordernumber_counters widefat" cellspacing="0">
 					<?php
 						$columns = apply_filters( 'woocommerce_ordernumber_counters_columns', array(
-							'type'     => __( '', 'woocommerce-advanced-ordernumbers' ),
-							'name'     => __( 'Counter name', 'woocommerce-advanced-ordernumbers' ),
-							'value'    => __( 'Counter value', 'woocommerce-advanced-ordernumbers' ),
+							'type'     => self::__( ''),
+							'name'     => self::__( 'Counter name'),
+							'value'    => self::__( 'Counter value'),
 							'settings' => ''
 						) );
 					?>
@@ -455,8 +477,8 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 							<td class="counter_type"></td>
 							<td colspan=3 class='counter_add'>
 								<div class='ordernumber-counter-addbtn ordernumber-btn' onClick="ajaxAddCounter(this, 'ordernumber')">
-									<div class='ordernumber-ajax-loading'><img src='<?php echo plugins_url( 'assets/images/icon-16-new.png', __FILE__ ); ?>' class='ordernumber-counter-addbtn' /></div>
-									<?php _e('Add new counter', 'woocommerce-advanced-ordernumbers'); ?>
+									<div class='ordernumber-ajax-loading'><img src='<?php echo self::img_url( 'icon-16-new.png' ); ?>' class='ordernumber-counter-addbtn' /></div>
+									<?php _e('Add new counter'); ?>
 								</div>
 							</td>
 						</tr>
@@ -470,17 +492,17 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 			public function create_admin_counter_row ($type, $format, $value=0) {
 				$html =	"
 					<tr class='counter_row counter_type_" . $type . "'>
-						<td class='counter_type'>" . __($type, 'wooocommerce-advanced-ordernumbers' ) . "</td>
-						<td class='counter_format'>" . (empty($format)?("<i>".__("[Global]", 'woocommerce-advanced-ordernumbers')."</i>"):esc_html($format)) . "</td>
+						<td class='counter_type'>" . self::__($type, 'wooocommerce-advanced-ordernumbers' ) . "</td>
+						<td class='counter_format'>" . (empty($format)?("<i>".self::__("[Global]")."</i>"):esc_html($format)) . "</td>
 						<td class='counter_value'>" . esc_html($value) . "</td>
 						<td class='counter_buttons'>
 							<div class='ordernumber-ajax-loading'>
-							<img src='" . plugins_url( 'assets/images/icon-16-edit.png', __FILE__ ) . "' 
+							<img src='" . self::img_url( 'icon-16-edit.png' ) . "' 
 										class='ordernumber-counter-editbtn ordernumber-btn' 
 										onClick='ajaxEditCounter(this, " . json_encode($type) . ", " . json_encode($format) . ", " . json_encode($value) . ")' />
 							</div>
 							<div class='ordernumber-ajax-loading'>
-								<img src='" . plugins_url( 'assets/images/icon-16-delete.png', __FILE__ ) . "' 
+								<img src='" . self::img_url( 'icon-16-delete.png' ) . "' 
 										class='ordernumber-counter-deletebtn ordernumber-btn' 
 										onClick='ajaxDeleteCounter(this, " . json_encode($type) . ", " . json_encode($format) . ", " . json_encode($value) . ")' />
 							</div>
@@ -556,7 +578,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				$json = array('action' => 'add_counter', 'success' => 0);
 				if ($this->_getCounter($type, $format, -1) != -1) {
 					// Counter already exists => error message
-					$json['error'] = sprintf(__('Counter "%s" already exists, cannot create again.'), $format);
+					$json['error'] = sprintf(self::__('Counter "%s" already exists, cannot create again.'), $format);
 				} else {
 					$json['success'] = $this->_setCounter($type, $format, $value);
 					$json['newrow']  = $this->create_admin_counter_row($type, $format, $value);
@@ -570,12 +592,13 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				wp_send_json($json);
 			}
 			
-			/**
-			 * Variable replacements:
-			 *   - Random strings/digits
-			 *   - Order properties
-			 *   - User properties
-			 */
+			
+			
+			/** ***********************************************************
+			 * 
+			 *  REPLACEMENT FUNCTIONS
+			 *
+			 **************************************************************/
 			
 			/* Return a random "string" of the given length taken from the given alphabet */
 			static function randomString($alphabet, $len) {
@@ -603,42 +626,37 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 				}
 				return self::randomString ($alphabet, $len);
 			}
-    
-
-			/* replace the variables in the given format. $type indicates the type of number, currently only 'ordernumber', because WooCommerce does not support invoices or customer numbers. We might allow the shop owner to customize the order password, though. */
-			function replace_fields ($fmt, $type, $order) {
-				// First, replace all randomXXX[n] fields. This needs to be done with a regexp and a callback:
-				$fmt = preg_replace_callback ('/\[(random)(.*?)([0-9]*?)\]/', array($this, 'replaceRandom'), $fmt);
-        
-				$reps = array (
-					"[year]" => date ("Y"),
-					"[year2]" => date ("y"),
-					"[month]" => date("m"),
-					"[day]" => date("d"),
-					"[hour]" => date("H"),
-					"[hour12]" => date("h"),
-					"[ampm]" => date("a"),
-					"[minute]" => date("i"),
-					"[second]" => date("s"),
-					"[orderid]" => $order->id,
-				);
+	
+			protected function setupDateTimeReplacements (&$reps, $order, $nrtype) {
+				$utime = microtime(true);
+				$reps["[year]"] = date ("Y", $utime);
+				$reps["[year2]"] = date ("y", $utime);
+				$reps["[month]"] = date("m", $utime);
+				$reps["[day]"] = date("d", $utime);
+				$reps["[hour]"] = date("H", $utime);
+				$reps["[hour12]"] = date("h", $utime);
+				$reps["[ampm]"] = date("a", $utime);
+				$reps["[minute]"] = date("i", $utime);
+				$reps["[second]"] = date("s", $utime);
+				$milliseconds = (int)(1000*($utime - (int)$utime));
+				$millisecondsstring = sprintf('%03d', $milliseconds);
+				$reps["[decisecond]"] = $millisecondsstring[0];
+				$reps["[centisecond]"] = substr($millisecondsstring, 0, 2);
+				$reps["[millisecond]"] = $millisecondsstring;
+			}
 
-				$reps["[userid]"]      = $order->get_user_id();
-				$reps["[ipaddress]"]   = $order->customer_ip_address;
-				$reps["[orderstatus]"] = $order->get_status();
-				$reps["[email]"]       = $order->billing_email;
-        
-				
-				$reps["[firstname]"] = $order->billing_first_name;
-				$reps["[lastname]"]  = $order->billing_last_name;
+			protected 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]"]   = $order->billing_company;
-				$reps["[zip]"]       = $order->billing_postcode;
-				$reps["[postcode]"]  = $order->billing_postcode;
-				$reps["[city]"]      = $order->billing_city;
+				$reps["[company]"]   = $address->billing_company;
+				$reps["[zip]"]       = $address->billing_postcode;
+				$reps["[postcode]"]  = $address->billing_postcode;
+				$reps["[city]"]      = $address->billing_city;
         
-				$country = $order->billing_country;
-				$state = $order->billing_state;
+				$country = $address->billing_country;
+				$state = $address->billing_state;
 				$allcountries = WC()->countries->get_countries();
 				$states = WC()->countries->get_states($country);
 				$reps["[country]"]     = $country;
@@ -646,28 +664,136 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 
 				$reps["[state]"]       = $state;
 				$reps["[statename]"]   = ( $country && $state && isset( $states[ $country ][ $state ] ) ) ? $states[ $country ][ $state ] : $state;
+			}
+			
+			protected function setupStoreReplacements (&$reps, $order, $nrtype) {
+			}
+    
+			protected function setupOrderReplacements (&$reps, $order, $nrtype) {
+				$reps["[orderid]"] = $order->id;
+				$reps["[ipaddress]"]   = $order->customer_ip_address;
 				
-				$reps["[articles]"]    = $order->get_item_count();
+				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);
+	
+				$reps["[articles]"]    = $order->get_item_count();
 // 				$reps["[downloadpermitted]"] = $order->is_download_permitted();
 // 				$reps["[hasdownloads]"] = $order->has_downloadable_item();
 // 				$reps["[coupons]"] = $order->get_used_coupons();
-				
-				if ($type != 'ordernumber') {
-					$reps["[ordernumber]"] = $order->get_order_number();
-				}
-				$user = $order->get_user();
-				if ($user) {
-//					TODO: Shall we supply a variable for the user's login / display name?
-// 					$reps["[user]"] = print_r($user,1);
-// 					if (isset($order->username)) $reps["[username]"] = $order->username;
+				$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();
+			}
+   
+			protected function setupShippingReplacements(&$reps, $order, $nrtype) {
+// 				$reps["[shippingmethod]"] = $order->getShippingMethod();
+			}
+			
+			/*protected function setupInvoiceReplacements (&$reps, $invoice, $order, $nrtype) {
+				$reps["[invoiceid]"] = $invoice->getId();
+			}*/
+
+			protected function setupReplacements($nrtype, $order) {
+				$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);
+				return $reps;
+			}
+
+			
+			protected function applyCustomVariables ($nrtype, $order, $reps, $customvars) {
+				foreach ($customvars as $c) {
+					$conditionvar = strtolower($c['conditionvar']);
+					$op = $c['conditionop'];
+
+					$found = false;
+					$match = false;
+					$compareval = null;
+
+					if (isset($reps[$conditionvar])) {
+						$found = true;
+						$compareval = $reps[$conditionvar];
+					} elseif (isset($reps['['.$conditionvar.']'])) {
+						$found = true;
+						$compareval = $reps['['.$conditionvar.']'];
+					}/* elseif ($order && $compareval = $order->getData($conditionvar)) {
+						// TODO: Handle order property
+						$found = true;
+					}*/ else {
+						// TODO: Handly other possible properties!
+						// TODO: Print out warning that variable could not be found.
+					}
+					if ($found) {
+						$condval = $c['conditionval'];
+						switch ($op) {
+							case 'equals': 
+									$match = ($compareval == $condval); break;
+							case 'contains':
+									if (is_array($compareval)) {
+										$match = in_array($condval, $compareval);
+									} else {
+										$match = strpos ($compareval, $condval);
+									}
+									break;
+							case 'smaller':
+									$match = ($compareval<$condval); break;
+							case 'smallerequal':
+									$match = ($compareval<=$condval); break;
+							case 'larger':
+									$match = ($compareval>$condval); break;
+							case 'largerequal':
+									$match = ($compareval>=$condval); break;
+							case 'startswith':
+									$match = (substr("$compareval", 0, strlen("$condval")) === "$condval"); break;
+							case 'endswith':
+									$match = (substr("$compareval", -strlen("$condval")) === "$condval"); break;
+						}
+					} elseif (empty($conditionvar)) {
+						$match = true;
+					}
+					if ($match) {
+						$varname = '['.strtolower($c['newvar']).']';
+						$reps[$varname] = $c['newval'];
+					}
 				}
+				return $reps;
+			}
 
-				// Allow customization via plugins: filter function($reps, $order, $type, $fmt)
-				$reps = apply_filters( 'opentools_ordernumber_replacements', $reps, $order, $type, $fmt);
+			protected function doReplacements ($fmt, $reps) {
+				// First, replace all random...[n] fields. This needs to be done with a regexp and a callback:
+				$fmt = preg_replace_callback ('/\[(random)(.*?)([0-9]*?)\]/', array($this, 'replaceRandom'), $fmt);
 				return str_ireplace (array_keys($reps), array_values($reps), $fmt);
 			}
 
+			// Allow the user to override the format like any other custom variable:
+			protected function determineNumberFormatString($fmt, $type, $order, $reps) {
+				if (isset($reps['['.$type.'_format]'])) {
+					return $reps['['.$type.'_format]'];
+				} else {
+					return $fmt;
+				}
+			}
+			
+
+			/* replace the variables in the given format. $type indicates the type of number, currently only 'ordernumber', because WooCommerce does not support invoices or customer numbers. We might allow the shop owner to customize the order password, though. */
+			function replace_fields ($fmt, $type, $order, $customvars) {
+				$reps = $this->setupReplacements ($type, $order);
+				$reps = $this->applyCustomVariables ($type, $order, $reps, $customvars);
+				$format = $this->determineNumberFormatString($fmt, $type, $order, $reps);
+				return $this->doReplacements($format, $reps);
+			}
+			
 			function create_ordernumber($orderid, $order, $type='ordernumber') {
 				if (get_option('customize_'.$type, 'false')) {
 					$fmt     = get_option ($type.'_format',  "#");
@@ -675,8 +801,9 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g
 					$padding = get_option ($type.'_padding', 1);
 					$step    = get_option ($type.'_step',    1);
 					$start   = get_option ($type.'_start',   1)-$step; // The counter contains the PREVIOUS number!
+					$customvars = get_option ('ordernumber_variables',   array());
 
-					$nr = $this->replace_fields ($fmt, $type, $order);
+					$nr = $this->replace_fields ($fmt, $type, $order, $customvars);
 
 					// Split at a | to get the number format and a possibly different counter increment format
 					// If a separate counter format is given after the |, use it, otherwise reuse the number format itself as counter format