woocommerce-advanced-ordernumbers.php 15 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
/**
 * Plugin Name: Advanced Ordernumbers
 * Plugin URI: http://open-tools.net/WooCommerce/Advanced-Ordernumbers.php
 * Description: Lets the user freely configure the order numbers in WooCommerce.
 * Version: 0.1.0
 * Author: Open Tools, Reinhold Kainhofer
 * Author URI: http://open-tools.net
 * Text Domain: woocommerce-advanced-ordernumbers
 * Domain Path: 
 * License: GPL2+
 WC requires at least: 2.2
WC tested up to: 2.3
*/

/**
 * The structure of this plugin follows the tutorial:
 * http://www.yaconiello.com/blog/how-to-write-wordpress-plugin/
 */
 
if ( ! defined( 'ABSPATH' ) ) { 
	exit; // Exit if accessed directly
}
/**
 * Check if WooCommerce is active
 **/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
    // Put your plugin code here
    // Load the language files
30
	load_plugin_textdomain('opentools-ordernumbers', false, basename( dirname( __FILE__ ) ) . '/languages' );
31
32
33
34
35
36
37
38

	if (!class_exists("OpenToolsOrdernumbers")) {
		class OpenToolsOrdernumbers {
			/**
			 * Construct the plugin object
			 */
			public function __construct()
			{
39
				$plugin = plugin_basename(__FILE__); 
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109


				// 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' ),
						'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' ),
						'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' ),
						'desc_tip'	=> true,
						'id' 		=> 'ordernumber_format',
						'default'	=> '#',
						'type' 		=> 'text',
					),
					array(
						'title'		=> __( 'Global', 'woocommerce-advanced-ordernumbers' ),
						'desc' 		=> __( 'Counter Scope', 'woocommerce-advanced-ordernumbers' ),
						'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' ),
						'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' ),
						'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' ),
						'desc_tip'	=> true,
						'id' 		=> 'ordernumber_step',
						'type' 		=> 'number',
						'default'	=> '1'
					),
					array( 'type' => 'sectionend', 'id' => 'ordernumber_options' ),
					
					// TODO: customize order password, and other numbers!
				);
				// Default options

				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');

110
				// register actions
111
112
113
114
115
116
117
118
119
120
121
122
// 				add_action( 'admin_init', array(&$this, 'admin_init'));
// 				add_action( 'admin_menu', array(&$this, 'add_menu'));
				// TODO: Find the proper action hooks to hook into:
				add_filter( 'woocommerce_get_sections_checkout', array($this, 'add_admin_section'),1);
// 				add_filter( 'woocommerce_get_settings_checkout', array( $this, 'admin_settings' ), 20, 2);
				// The checkout page assumes all subpages are payment gateways, so we have to override this:
				add_action( 'woocommerce_settings_checkout', array( $this, 'output' ) );
				add_action( 'woocommerce_settings_save_checkout', array( $this, 'save' ) );
				
				add_action( 'woocommerce_update_options_catalog', array( $this, 'save_admin_settings' ) ); // < 2.1
				add_action( 'woocommerce_update_options_products', array( $this, 'save_admin_settings' ) ); // 2.1 +

123
124
125
				// register filters
				add_filter("plugin_action_links_$plugin", array(&$this, 'plugin_settings_link'));
				add_filter ('woocommerce_order_number', array(&$this, 'get_ordernumber'), 10, 2/*<= Also get the order object! */);
126
127
			}
    
128
129
			// Activate the plugin
			public static function activate() {}
130
    
131
132
133
134
135
136
137
138
139
140
141
142
143
144
			// Deactivate the plugin
			public static function deactivate() {}

			function add_admin_section($sections) {
				$sections['ordernumber'] = __( 'Order Numbers', 'woocommerce-advanced-ordernumbers');
				return $sections;
			}
			
			public function output() {
				global $current_section;
				if ($current_section == 'ordernumber') {
					$settings = $this->settings;
					WC_Admin_Settings::output_fields( $settings );
				}
145
146
			}

147
148
149
150
151
152
			public function save() {
				global $current_section;
				if ($current_section == 'ordernumber') {
					$settings = $this->settings;
					WC_Admin_Settings::save_fields( $settings );
				}
153
			}
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

// 			// Save the settings
// 			function save_admin_settings() {
// 				woocommerce_update_options( $this->settings );
// 			}

// 			/**
// 			 * hook into WP's admin_init action hook
// 			 */
// 			public function admin_init()
// 			{
// 				// Set up the settings for this plugin
// 				$this->init_settings();
// 				// Possibly do additional admin_init tasks
// 			}
			
// 			/**
// 			* Initialize some custom settings
// 			*/     
// 			public function init_settings()
// 			{
// 				// register the settings for this plugin
// 				// TODO: Properly design the set of options needed
// 				register_setting('opentools-ordernumbers-group', 'customize_ordernumbers');
// 				register_setting('opentools-ordernumbers-group', 'ordernumber_format');
// 				register_setting('opentools-ordernumbers-group', 'ordernumber_counter_scope');
// 			}
			
// 			/**
// 			 * add a menu
// 			 */     
// 			public function add_menu()
// 			{
// 				// TODO: Move this inside the WooCommerce configuration!
// 				add_options_page(
// 					'Advanced Ordernumber Plugin Settings', // The title to be displayed in the browser window for this page.
// 					'OpenTools Advanced Ordernumbers',      // The text to be displayed for this menu item 
// 					'manage_options',                       // Which type of users can see this menu item
// 					'opentools-ordernumbers',               // The unique ID - that is, the slug - for this menu item
// 					array(&$this, 'plugin_settings_page')   // The name of the function to call when rendering this menu's page
// 				);
// 			}
 

// 			function plugin_settings_link($links)
// 			{ 
// 				$settings_link = '<a href="options-general.php?page=opentools-ordernumbers">Settings</a>'; 
// 				array_unshift($links, $settings_link); 
// 				return $links; 
// 			}

// 			/**
// 			 * Menu Callback
// 			 */
// 			public function plugin_settings_page()
// 			{
// 				if(!current_user_can('manage_options'))
// 				{
// 					wp_die(__('You do not have sufficient permissions to access this page.'));
// 				}
// 
// 				// Render the settings template
// 				include(sprintf("%s/templates/settings.php", dirname(__FILE__)));
// 			}
			
219
220
			
			/**
221
222
223
224
225
226
227
228
229
			 * Counter handling (simple loading/storing counters)
			 */
			function _getCounter($type, $format, $start=1) {
				$count = get_option ('ordernumber-counter-'.$type.'-'.$format, $start);
				return $count;
			}
			// Insert new counter value into the db or update existing one
			function _setCounter($type, $format, $value) {
				return update_option('ordernumber-counter-'.$type.'-'.$format, $value);
230
231
			}
			
232
			
233
			/**
234
235
236
237
238
239
240
241
242
243
244
245
246
247
			 * Variable replacements:
			 *   - Random strings/digits
			 *   - Order properties
			 *   - User properties
			 */
			
			/* Return a random "string" of the given length taken from the given alphabet */
			static function randomString($alphabet, $len) {
				$alen = strlen($alphabet);
				$r = "";
				for ($n=0; $n<$len; $n++) {
					$r .= $alphabet[mt_rand(0, $alen-1)];
				}
				return $r;
248
249
			}

250
251
252
253
254
255
256
257
258
259
260
261
262
			function replaceRandom ($match) {
				/* the regexp matches (random)(Type)(Len) as match, Type and Len is optional */
				$len = ($match[3]?$match[3]:1);
				// Fallback: If no Type is given, use Digit
				$alphabet = "0123456789";
				// Select the correct alphabet depending on Type
				switch (strtolower($match[2])) {
					case "digit": $alphabet = "0123456789"; break;
					case "hex": $alphabet = "0123456789abcdef"; break;
					case "letter": $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; break;
					case "uletter": $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; break;
					case "lletter": $alphabet = "abcdefghijklmnopqrstuvwxyz"; break;
					case "alphanum": $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; break;
263
				}
264
265
266
267
268
269
270
271
272
273
				return self::randomString ($alphabet, $len);
			}
    
			/* Extract the country information from the given ID */
// 			static function getCountryFromID ($country_id) {
// 				$db = JFactory::getDBO();
// 				$query = 'SELECT * FROM `#__virtuemart_countries` WHERE `virtuemart_country_id` = ' . (int)$country_id;
// 				$db->setQuery($query);
// 				return $db->loadObject();
// 			}
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337


			/* Type 0 means order number, type 1 means invoice number, type 2 means customer number, 3 means order password */
			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,
					"[userid]" => $order->get_user_id(),
				);
// 				if (isset($order->virtuemart_vendor_id)) $reps["[vendorid]"] = $order->virtuemart_vendor_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;

				$reps["[company]"] = $order->billing_company;
				$reps["[zip]"] = $order->billing_postcode;
				$reps["[postcode]"] = $order->billing_postcode;
				$reps["[city]"] = $order->billing_city;
        
				$country = $order->billing_country;
				$state = $order->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;
				
				$reps["[articles]"] = $order->get_item_count();
				$reps["[currency]"] = $order->get_order_currency();
				$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;
				}
				// Allow customization via plugins: filter function($reps, $order, $type, $fmt)
				$reps = apply_filters( 'opentools_ordernumber_replacements', $reps, $order, $type, $fmt);
// 				return print_r($reps,1);
				return str_ireplace (array_keys($reps), array_values($reps), $fmt);
338
			}
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

			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!

					$nr = $this->replace_fields ($fmt, $type, $order);

					// 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);
					update_post_meta( $orderid, 'Order Number', $number );
					return $number;
				} else {
					return $orderid;
				}
			}
	
369
370
371
372
			/** 
			 * The hook to customize order numbers (requests the order number from the database; creates a new ordernumber if no entry exists in the database)
			 */
			function get_ordernumber($orderid, $order) {
373
				$stored_number = get_post_meta( $orderid, 'Order Number', 'true');
374
375
				if (!empty($stored_number)) {
					return $stored_number;
376
				} elseif (get_option('customize_ordernumber', 'false')) {
377
					// create a new one (if this is a new order, otherwise we don't have/generate a number!)
378
379
					// TODO: Check whether this is a new number! Otherwise, do NOT create an order number
					$number = $this->create_ordernumber($orderid, $order, 'ordernumber');
380
					return $number;
381
382
383
				} else {
					print("<h1>Order number creation is DISABLED</h1>");
					return $orderid;
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
				}
			}

		}
	}

	if (class_exists("OpenToolsOrdernumbers")) {
		// Installation and uninstallation hooks
		register_activation_hook(__FILE__, array('OpenToolsOrdernumbers', 'activate'));
		register_deactivation_hook(__FILE__, array('OpenToolsOrdernumbers', 'deactivate'));

		// instantiate the plugin class
		$ordernumber_plugin = new OpenToolsOrdernumbers();
	}
 
}