From 6327cf306d2426e11086f378a1756678daae8e60 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer <reinhold@kainhofer.com> Date: Sun, 19 Apr 2015 20:22:46 +0200 Subject: [PATCH] Implement counter formatting/start/step directly in thee format --- TODO | 5 +- woocommerce-advanced-ordernumbers.php | 178 +++++++++++++++++--------- 2 files changed, 119 insertions(+), 64 deletions(-) diff --git a/TODO b/TODO index 19aff74..624b223 100644 --- a/TODO +++ b/TODO @@ -4,13 +4,12 @@ OpenTools Advanced Ordernumbers for WooCommerce - Open TODOs - Make sure the numbers are generated only for new orders, not for exsiting ones - Check REST API - Would it make sense to configure the order password format? -- Implement custom variables - Find out how multisite works and make the plugin work with it - Add action to create an updated / new order number for an existing order - implement woocommerce_hidden_order_itemmeta hook to hide the order number post meta? - Use $order->order_date for the date-relating fields! - Collect and return php warning messages (i.e. all other output) in the AJAX call and return it inside the JSON rather than as extra HTML. - +- Create order number also when ordering in the frontend HOOKS for order handling: @@ -37,4 +36,4 @@ woocommerce_new_order', $order_id ); Order created in BackEnd: Created: wp_insert_post => Assign placeholder (no address yet) -Modified: \ No newline at end of file +Modified: diff --git a/woocommerce-advanced-ordernumbers.php b/woocommerce-advanced-ordernumbers.php index 062a7d5..b48c436 100644 --- a/woocommerce-advanced-ordernumbers.php +++ b/woocommerce-advanced-ordernumbers.php @@ -85,11 +85,12 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g ), array( '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' => 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. 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' => 'ordernumber_format', 'default' => '#', 'type' => 'text', + 'css' => 'width: 100%', ), array( 'title' => self::__( 'Use global counter'), @@ -97,32 +98,32 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g 'desc_tip' => true, 'id' => 'ordernumber_global', 'type' => 'checkbox', - 'default' => 'no' - ), - array( - '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' => self::__( 'Counter Start'), - 'desc' => self::__( 'Start value for each new counter'), - 'desc_tip' => true, - 'id' => 'ordernumber_start', - 'type' => 'number', - 'default' => '1' - ), - array( - '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', - 'default' => '1' + 'default' => 'no', ), +// array( +// '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' => self::__( 'Counter Start'), +// 'desc' => self::__( 'Start value for each new counter'), +// 'desc_tip' => true, +// 'id' => 'ordernumber_start', +// 'type' => 'number', +// 'default' => '1' +// ), +// array( +// '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', +// 'default' => '1' +// ), array( 'type' => 'sectionend', 'id' => 'ordernumber_options' ), // TODO: customize order password, and other numbers! @@ -158,10 +159,10 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g add_option ('customize_ordernumber', '0'); add_option ('ordernumber_format', "#"); - add_option ('ordernumber_global', '0'); - add_option ('ordernumber_padding', '1'); - add_option ('ordernumber_start', '1'); - add_option ('ordernumber_step', '1'); + add_option ('ordernumber_global', 'no'); +// add_option ('ordernumber_padding', '1'); +// add_option ('ordernumber_start', '1'); +// add_option ('ordernumber_step', '1'); add_option ('ordernumber_variables', array()); @@ -712,7 +713,7 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g } - protected function applyCustomVariables ($nrtype, $order, $reps, $customvars) { + protected function setupCustomVariables ($nrtype, $order, $reps, $customvars) { foreach ($customvars as $c) { $conditionvar = strtolower($c['conditionvar']); $op = $c['conditionop']; @@ -770,14 +771,8 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g return $reps; } - 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) { + protected function setupNumberFormatString($fmt, $type, $order, $reps) { if (isset($reps['['.$type.'_format]'])) { return $reps['['.$type.'_format]']; } else { @@ -785,38 +780,99 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g } } + 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); + } + + protected function extractCounterSettings ($fmt, $type, $ctrsettings) { + // First, extract all counter settings, i.e. all strings of the form [#####:startval/increment] or [####/increment:startval] + $regexp = '%\[(#+)(/([0-9]+))?(:([0-9]+))?(/([0-9]+))?\]%'; +// $counters = array(); + + if (preg_match($regexp, $fmt, $counters)) { + // $counters is an array of the form: + // Array ( + // [0] => [#####:100/3] + // [1] => ##### + // [2] => + // [3] => + // [4] => :100 + // [5] => 100 + // [6] => /3 + // [7] => 3 + // ) + $ctrsettings["${type}_padding"] = strlen($counters[1]); + if (!empty($counters[2])) { + // $counters[2] contains the whole "/n" part, while $counters[3] contains just the step itself + $ctrsettings["${type}_step"] = $counters[3]; + } + if (!empty($counters[4])) { + // $counters[4] contains the whole ":n" part, while $counters[5] contains just the start value itself + $ctrsettings["${type}_start"] = $counters[5]; + } + + if (!empty($counters[6])) { + // $counters[6] contains the whole ":n" part, while $counters[7] contains just the start value itself + $ctrsettings["${type}_step"] = $counters[7]; + } + +// print("<pre>Counters regexp matches: ".print_r($counters,1)."</pre>"); +// $ctrsettings["${type}_padding"] = + $fmt = preg_replace($regexp, "#", $fmt); + } else { +// print("<pre>No counters match the regexp '$regexp' in the format '$fmt'</pre>"); + } + // Replace all extended counter definitions by a single # + + // 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 + + + $parts = explode ("|", $fmt); + $ctrsettings["${type}_format"] = $parts[0]; + + $ctrsettings["${type}_counter"] = ($ctrsettings["${type}_global"]=='yes')?"":$parts[(count($parts)>1)?1:0]; + +// print("<pre>Counter settings are: ".print_r($ctrsettings,1)."</pre>"); + return $ctrsettings; + } /* 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 createNumber ($fmt, $type, $order, $customvars, $ctrsettings) { + $reps = $this->setupReplacements ($type, $order); + $reps = $this->setupCustomVariables ($type, $order, $reps, $customvars); + $format = $this->setupNumberFormatString($fmt, $type, $order, $reps); + $format = $this->doReplacements($format, $reps); + $ctrsettings = $this->extractCounterSettings ($format, $type, $ctrsettings); + + $countername = $ctrsettings["${type}_counter"]; + // Look up the current counter + $count = $this->_getCounter($type, $countername, $ctrsettings["${type}_start"] - $ctrsettings["${type}_step"]) + $ctrsettings["${type}_step"]; + $this->_setCounter($type, $countername, $count); + // return the format with the counter inserted + $number = str_replace ("#", sprintf('%0' . $ctrsettings["${type}_padding"] . 's', $count), $ctrsettings["${type}_format"]); + return $number; } function create_ordernumber($orderid, $order, $type='ordernumber') { if (get_option('customize_'.$type, 'false')) { $fmt = get_option ($type.'_format', "#"); - $global = get_option ($type.'_global', 1); - $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! + $ctrsettings = array( + "${type}_format" => '', + "${type}_counter" => '', + "${type}_global" => get_option ($type.'_global', 'no'), + "${type}_padding" => 1, + "${type}_step" => 1, + "${type}_start" => 1, +// "${type}_padding" => get_option ($type.'_padding', 1), +// "${type}_step" => get_option ($type.'_step', 1), +// "${type}_start" => get_option ($type.'_start', 1), + ); $customvars = get_option ('ordernumber_variables', array()); - $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 - $parts = explode ("|", $nr); - $format = $parts[0]; - - $counterfmt = ($global==1)?"":$parts[(count($parts)>1)?1:0]; - - // Look up the current counter - $count = $this->_getCounter($type, $counterfmt, $start) + $step; - $this->_setCounter($type, $counterfmt, $count); - // return the format with the counter inserted - $number = str_replace ("#", sprintf('%0' . $padding . 's', $count), $format); + $number = $this->createNumber ($fmt, $type, $order, $customvars, $ctrsettings); update_post_meta( $orderid, $this->ordernumber_meta, $number ); return $number; } else { -- GitLab