diff --git a/assets/css/ordernumber-counter.css b/assets/css/ordernumber-counter.css new file mode 100644 index 0000000000000000000000000000000000000000..40d4d37029be80bdbcfc8554240a9f7e404560fc --- /dev/null +++ b/assets/css/ordernumber-counter.css @@ -0,0 +1,47 @@ + +table.wc_ordernumber_counters { + border: 1px solid #888888; + width: inherit; +} + +table.wc_ordernumber_counters td, table.wc_ordernumber_counters th { + padding-bottom: 0px; + padding-top: 0px; +} +table.wc_ordernumber_counters thead th { + text-align: center; + width: auto; +} +td.counter_value { + text-align: center; +} + +table.wc_ordernumber_counters thead > tr:nth-child(odd) > th, +table.wc_ordernumber_counters tfoot > td.addcounter_row > th { + background: #E0E0E0; +} +table.wc_ordernumber_counters tbody > tr:nth-child(odd) > td { + background: #F0F0F0; +} +.ordernumber-btn { + cursor: pointer; +} + +col.counter_type, th.counter_type, td.counter_type { + display:none; +} + +table.wc_ordernumber_counters img { + padding: 0; + margin: 0; +} +div.ordernumber-ajax-loading, div.ordernumber-counter-addbtn { + display: inline; +} +div.ordernumber-ajax-loading, div.ordernumber-ajax-loading img.ordernumber-btn { + position: relative; + top: 0; left: 0; +} +div.ordernumber-ajax-loading img { + z-index:0; +} diff --git a/assets/images/icon-16-delete.png b/assets/images/icon-16-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..1573413858f535fc32cb0428d3275f639a5f74cc Binary files /dev/null and b/assets/images/icon-16-delete.png differ diff --git a/assets/images/icon-16-edit.png b/assets/images/icon-16-edit.png new file mode 100644 index 0000000000000000000000000000000000000000..b1bcf04bb12fe3186243c8becb73bb0b24795117 Binary files /dev/null and b/assets/images/icon-16-edit.png differ diff --git a/assets/images/icon-16-new.png b/assets/images/icon-16-new.png new file mode 100644 index 0000000000000000000000000000000000000000..fcd6a5a695d6efadc571362896612e17440e9cc1 Binary files /dev/null and b/assets/images/icon-16-new.png differ diff --git a/assets/images/loading.gif b/assets/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..94da6d80e05ef96d9d7551013d59c22551c0ae1a Binary files /dev/null and b/assets/images/loading.gif differ diff --git a/assets/images/loading.png b/assets/images/loading.png new file mode 100644 index 0000000000000000000000000000000000000000..ac0aa90cbc6fde315828934a2494ec1324b8af56 Binary files /dev/null and b/assets/images/loading.png differ diff --git a/assets/js/ordernumber-counter.js b/assets/js/ordernumber-counter.js new file mode 100644 index 0000000000000000000000000000000000000000..dff1e44af6636c71665c681c2dc80c2e554edd89 --- /dev/null +++ b/assets/js/ordernumber-counter.js @@ -0,0 +1,136 @@ + +String.Format = function () { + var s = arguments[0]; + for (var i = 0; i < arguments.length - 1; i++ ) { + var reg = new RegExp ("\\{" + i + "\\}", "gm"); + s = s.replace (reg, arguments[i + 1]); + } + return s; +} + +var getCounterData = function (btn) { + var row = jQuery (btn).parents ("tr.counter_row"); + return { row: row }; +} +var handleJSONResponse = function (json, counter) { +// updateMessages (json['messages'], "ordernumber"); + if (!json.authorized) { + alert (ajax_ordernumber.PLG_ORDERNUMBER_JS_NOT_AUTHORIZED); + } else if (json.error) { + alert (json.error); + } else { + // TODO: Which other error checks can we do? + } +} +var ajaxEditCounter = function (btn, nrtype, ctr, value) { + var counter = getCounterData (btn); + counter.type = nrtype; + counter.counter = ctr; + counter.value = value; + var value = NaN; + var msgprefix = ""; + while (isNaN (value) && (value != null)) { + value = prompt (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_EDITCOUNTER, msgprefix, counter.counter, counter.value), counter.value); + if (value != null) + value = parseInt (value); + if (isNaN (value)) + msgprefix = ajax_ordernumber.PLG_ORDERNUMBER_JS_INVALID_COUNTERVALUE; + } + if (value != null) { + var loading = jQuery ("img.wc-ordernumber-loading").first ().clone ().insertAfter (btn).show (); + jQuery.post ( + ajax_ordernumber.admin_url, + { + action: 'set_counter', + nrtype: counter.type, + counter: counter.counter, + value: value + }, + success: function ( data ) { + try { + var json = jQuery.parseJSON (data); + handleJSONResponse (json, counter); + } catch (e) { + alert (ajax_ordernumber.PLG_ORDERNUMBER_JS_JSONERROR + "\n" + e); + return; + } + if (json.success>0) { + jQuery (counter.row).children (".counter_value").text (value); + } else { + alert (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_MODIFY_FAILED, counter.counter)); + } + }, + error: function () { alert (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_MODIFY_FAILED, counter.counter)); }, + complete: function () { jQuery (loading).remove (); }, + }); + } +} +var ajaxDeleteCounter = function (btn, nrtype, ctr, value) { + var counter = getCounterData (btn); + counter.type = nrtype; + counter.counter = ctr; + counter.value = value; + var proceed = confirm (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_DELETECOUNTER, counter.counter, counter.value)); + if (proceed = = true) { + var loading = jQuery ("img.wc-ordernumber-loading").first ().clone ().insertAfter (btn).show (); + jQuery.post ( + ajax_ordernumber.admin_url, + { + action: 'delete_counter', + nrtype: counter.type, + counter: counter.counter + }, + success: function ( data ) { + try { + var json = jQuery.parseJSON (data); + handleJSONResponse (json, counter); + } catch (e) { + alert (ajax_ordernumber.PLG_ORDERNUMBER_JS_JSONERROR + "\n" + e); + return; + } + if (json.success>0) { + jQuery (counter.row).fadeOut (1500, function () { jQuery (counter.row).remove (); }); + } else { + alert (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_DELETE_FAILED, counter.counter)); + } + }, + error: function () { alert (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_DELETE_FAILED, counter.counter)); }, + complete: function () { jQuery (loading).remove (); }, + }); + } +} +var ajaxAddCounter = function (btn, nrtype) { + var row = jQuery (btn).parents ("tr.addcounter_row"); + var countername = prompt (ajax_ordernumber.PLG_ORDERNUMBER_JS_NEWCOUNTER); + if (countername != null) { + var loading = jQuery ("img.wc-ordernumber-loading").first ().clone ().insertAfter (jQuery (btn).find ("img.ordernumber-counter-addbtn")).show (); + jQuery.post ( + ajax_ordernumber.admin_url, + { + action: 'add_counter', + nrtype: nrtype, + counter: countername + + }, + success: function ( data ) { + var json = data ? jQuery.parseJSON (data) : null; + try { + var json = jQuery.parseJSON (data); + handleJSONResponse (json, null); + } catch (e) { + alert (ajax_ordernumber.PLG_ORDERNUMBER_JS_JSONERROR + "\n" + e); + return; + } + if (json.success>0) { + if (json.newrow) { + jQuery (row).before (jQuery (json.newrow)); + } + } else { + alert (String.Format (ajax_ordernumber.PLG_ORDERNUMBER_JS_ADD_FAILED, countername)); + } + }, + error: function () { alert (String.Format (vPLG_ORDERNUMBER_JS_ADD_FAILED, countername)); }, + complete: function () { jQuery (loading).remove (); }, + }); + } +} diff --git a/woocommerce-advanced-ordernumbers.php b/woocommerce-advanced-ordernumbers.php index 11cebcc3e8a4d081f1ecd33122133f8653f40f77..8fd07432d54f089f351627a99a5aa0082b500898 100644 --- a/woocommerce-advanced-ordernumbers.php +++ b/woocommerce-advanced-ordernumbers.php @@ -102,6 +102,33 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g array( 'type' => 'sectionend', 'id' => 'ordernumber_options' ), // 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' ), + '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' ), + 'desc' => __( 'View and modify the current counter values.', 'woocommerce-advanced-ordernumbers' ), + 'type' => 'title', + 'id' => 'ordernumber_counters' + ), + array( + 'id' => 'ordernumber_counters', + 'type' => 'ordernumber_counters', + ), + array( 'type' => 'sectionend', 'id' => 'ordernumber_counters' ), + ); // Default options @@ -111,12 +138,27 @@ if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', g add_option ('ordernumber_padding', '1'); add_option ('ordernumber_start', '1'); add_option ('ordernumber_step', '1'); + +// add_option ('ordernumber_counters', '1'); - // register actions - add_filter( 'woocommerce_get_sections_checkout', array($this, 'add_admin_section')); + // register filters and actions + + // CONFIGURATION SCREENS + add_filter( 'woocommerce_get_sections_checkout', array($this, 'add_admin_section')); // The checkout settings page assumes all subpages are payment gateways, so we have to override this and manually pass our settings: - add_action( 'woocommerce_settings_checkout', array( $this, 'settings_output' ) ); - add_action( 'woocommerce_settings_save_checkout', array( $this, 'settings_save' ) ); + add_action( 'woocommerce_settings_checkout', array( $this, 'settings_output' ) ); + add_action( 'woocommerce_settings_save_checkout', array( $this, 'settings_save' ) ); + add_action( 'woocommerce_admin_field_ordernumber_variables', array( $this, 'admin_field_variables' ) ); + add_action( 'woocommerce_admin_field_ordernumber_counters', array( $this, 'admin_field_counters' ) ); + + add_action( 'admin_print_styles-woocommerce_page_wc-settings', array($this, 'print_admin_styles')); + add_action( 'admin_print_scripts-woocommerce_page_wc-settings', array($this, 'print_admin_scripts')); + + // AJAX counter modifications + add_action( 'wp_ajax_set_counter', array($this, 'counter_set_callback') ); + add_action( 'wp_ajax_add_counter', array($this, 'counter_add_callback') ); + add_action( 'wp_ajax_delete_counter', array($this, 'counter_delete_callback') ); + // Add the ordernumber post meta to the search in the backend add_filter( 'woocommerce_shop_order_search_fields', array($this, 'order_search_fields')); // Sort the order list in the backend by order number rather than ID, make sure this is called LAST so we modify the defaults passed as arguments @@ -166,6 +208,143 @@ 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_enqueue_style('ordernumber-counter-style'); + } + /** + * Print the JS for the counter values and counter variables tables to the page header in the WC backend admin setting page + */ + public function print_admin_scripts() { + + wp_register_script( 'ordernumber-counter-script', plugins_url( 'assets/js/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_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}"); + + // in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.we_value + wp_localize_script( 'ordernumber-counter-script', 'ajax_ordernumber', $localizations ); + } + + /** + * Render the Custom Variables configuration table + */ + public function admin_field_variables($settings) { + echo "<h2>TODO!</h2>"; + + } + + /** + * Render the Counter Values modification table + */ + public function admin_field_counters ($settings) { + + // First, get all counter names: +// print "<pre>All options: ".print_r(wp_load_alloptions(),1)."</pre>"; + $counters = array(); + $pfxlen = strlen($this->ordernumber_counter_prefix ); + foreach (wp_load_alloptions() as $name => $value) { + if (substr($name, 0, $pfxlen) == $this->ordernumber_counter_prefix) { + $parts = explode('-', substr($name, $pfxlen), 2); + if (sizeof($parts)==1) { + array_unshift($parts, 'ordernumber'); + } + $counters[] = array( + 'type' => $parts[0], + 'name' => $parts[1], + 'value' => $value, + ); + } + } + ?> + + <tr valign="top"> + <th scope="row" class="titledesc"><?php _e( 'Current Counters:', 'woocommerce' ) ?></th> + <td class="forminp"> + <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;"/> + <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' ), + 'settings' => '' + ) ); + ?> + <thead> + <tr> + <?php + foreach ( $columns as $key => $column ) { + echo '<th class="counter_' . esc_attr( $key ) . '">' . esc_html( $column ) . '</th>'; + } + ?> + </tr> + </thead> + <colgroup> + <?php + foreach ($columns as $key => $column) { + echo '<col class="counter_' . esc_attr($key) . '" />'; + } + ?> + </colgroup> + + <tbody> + <?php + foreach ($counters as $counter) {?> + <tr class='counter_row counter_type_<?php echo $counter['type'];?>'> + <td class='counter_type'><?php _e($counter['type'], 'wooocommerce-advanced-ordernumbers' ); ?></td> + <td class='counter_format'><?php echo esc_html($counter['name']); ?></td> + <td class='counter_value'><?php echo esc_html($counter['value']); ?></td> + <td class='counter_buttons'> + <div class='ordernumber-ajax-loading'> + <img src='<?php echo plugins_url( 'assets/images/icon-16-edit.png', __FILE__ ); ?>' + class='ordernumber-counter-editbtn ordernumber-btn' + onClick='ajaxEditCounter(this, <?php echo json_encode($counter['type']); ?>, <?php echo json_encode($counter['name']); ?>, <?php echo $counter['value']; ?>)' /> + </div> + <div class='ordernumber-ajax-loading'> + <img src='<?php echo plugins_url( 'assets/images/icon-16-delete.png', __FILE__ ); ?>' + class='ordernumber-counter-deletebtn ordernumber-btn' + onClick='ajaxDeleteCounter(this, <?php echo json_encode($counter['type']); ?>, <?php echo json_encode($counter['name']); ?>, <?php echo $counter['value']; ?>)' /> + </div> + </td> + </tr> + <?php + } ?> + </tbody> + <tfoot> + <tr class='addcounter_row'> + <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> + </td> + </tr> + </tfoot> + </table> + </td> + </tr> + <?php + } + + + /** * Hook to add the order numer post meta field to the searchable field * (so the admin can search for the order number in the backend)