Skip to content
Snippets Groups Projects
Commit 41d40415 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

First version of library factorization

parent ca082e16
No related branches found
No related tags found
No related merge requests found
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 > tr.addcounter_row > td {
background: #E0E0E0;
}
table.wc_ordernumber_counters tbody > tr:nth-child(even) > 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;
}
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 && !json.success) {
alert (ajax_ordernumber.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.ORDERNUMBER_JS_EDITCOUNTER, msgprefix, counter.counter, counter.value), counter.value);
if (value != null)
value = parseInt (value);
if (isNaN (value))
msgprefix = ajax_ordernumber.ORDERNUMBER_JS_INVALID_COUNTERVALUE;
}
if (value != null) {
var loading = jQuery ("img.ordernumber-loading").first ().clone ().insertAfter (btn).show ();
jQuery.ajax ({
type: "POST",
url: ajax_ordernumber.ajax_url,
data: {
action: 'set_counter',
nrtype: counter.type,
counter: counter.counter,
value: value,
},
success: function ( json ) {
try {
handleJSONResponse (json, counter);
} catch (e) {
alert (ajax_ordernumber.ORDERNUMBER_JS_JSONERROR + "\n" + e);
return;
}
if (json.success>0) {
jQuery (counter.row).children (".counter_value").text (value);
} else {
alert (String.Format (ajax_ordernumber.ORDERNUMBER_JS_MODIFY_FAILED, counter.counter));
}
},
error: function () { alert (String.Format (ajax_ordernumber.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.ORDERNUMBER_JS_DELETECOUNTER, counter.counter, counter.value));
if (proceed == true) {
var loading = jQuery ("img.ordernumber-loading").first ().clone ().insertAfter (btn).show ();
jQuery.ajax ({
type: "POST",
dataType: "json",
url: ajax_ordernumber.ajax_url,
data: {
action: 'delete_counter',
nrtype: counter.type,
counter: counter.counter,
},
success: function ( json ) {
try {
handleJSONResponse (json, counter);
} catch (e) {
alert (ajax_ordernumber.ORDERNUMBER_JS_JSONERROR + "\n" + e);
return;
}
if (json.success>0) {
jQuery (counter.row).fadeOut (1200, function () { jQuery (counter.row).remove (); });
} else {
alert (String.Format (ajax_ordernumber.ORDERNUMBER_JS_DELETE_FAILED, counter.counter));
}
},
error: function () { alert (String.Format (ajax_ordernumber.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.ORDERNUMBER_JS_NEWCOUNTER);
if (countername != null) {
var loading = jQuery ("img.ordernumber-loading").first ().clone ().insertAfter (jQuery (btn).find ("img.ordernumber-counter-addbtn")).show ();
jQuery.ajax ({
type: "POST",
dataType: "json",
url: ajax_ordernumber.ajax_url,
data: {
action: 'add_counter',
nrtype: nrtype,
counter: countername,
value: 0,
},
success: function ( json ) {
try {
handleJSONResponse (json, null);
} catch (e) {
alert (ajax_ordernumber.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.ORDERNUMBER_JS_ADD_FAILED, countername));
}
},
error: function () { alert (String.Format (ajax_ordernumber.ORDERNUMBER_JS_ADD_FAILED, countername)); },
complete: function () { jQuery (loading).remove (); },
});
}
}
var ordernumberVariablesAddRow = function (template, element) {
jQuery("#" + template + " tr").clone(true)
.appendTo("table#" + element + " tbody")
.find('input,select,button,img')
.removeAttr('disabled');
jQuery("tr#ordernumber-replacements-empty-row")
.addClass("rowhidden")
.find('input')
.attr('disabled', 'disabled');
}
jQuery(document).ready (function () {
jQuery('img.ordernumber-replacement-deletebtn').click(
function () {
jQuery(this).closest('tr').remove();
var count = jQuery(this).closest('table').find('tbody tr').length;
if (count==0) {
jQuery("tr#ordernumber-replacements-empty-row")
.removeClass("rowhidden")
.find('input,select,button,img')
.removeAttr('disabled');
}
}
);
});
table.ordernumber-countertable {
border: 1px solid #888888;
display: inline-table;
width: inherit;
}
table.ordernumber-countertable td, table.ordernumber-countertable th {
padding-bottom: 0px;
padding-top: 0px;
}
table.ordernumber-countertable thead th {
text-align: center;
width: auto;
}
table.ordernumber-countertable thead > tr:nth-child(odd) > th,
table.ordernumber-countertable tfoot > tr.addcounter_row > td {
background: #E0E0E0;
}
table.ordernumber-countertable tbody > tr:nth-child(even) > td {
background: #F0F0F0;
}
table.ordernumber-countertable.table-striped tbody > tr:nth-child(odd) > th {
background: #E0E0E0;
}
.ordernumber-btn {
cursor: pointer;
}
col.counter_type, th.counter_type, td.counter_type {
display:none;
}
td.counter_value {
text-align: center;
}
fieldset table.ordernumber-countertable 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;
}
img.ordernumber-loading {
display: none;
position: absolute;
top: 2px;
left: 0px;
z-index: 9999;
}
/* Counter custom variable replacements */
table.ordernumber_variables { table.ordernumber_variables {
border: 1px solid #888888; border: 1px solid #888888;
width: inherit; width: inherit;
...@@ -19,6 +86,9 @@ table.ordernumber_variables thead th { ...@@ -19,6 +86,9 @@ table.ordernumber_variables thead th {
td.counter_value { td.counter_value {
text-align: center; text-align: center;
} }
table.ordernumber_variables input {
background-color: rgba(255,255,255,0.75);
}
table.ordernumber_variables thead > tr:nth-child(odd) > th, table.ordernumber_variables thead > tr:nth-child(odd) > th,
table.ordernumber_variables tfoot > tr.addreplacement_row > td { table.ordernumber_variables tfoot > tr.addreplacement_row > td {
...@@ -54,4 +124,8 @@ col.variables_thenvar, col.variables_thenval { ...@@ -54,4 +124,8 @@ col.variables_thenvar, col.variables_thenval {
} }
.variables_then, .variables_settings { .variables_then, .variables_settings {
text-align: center; text-align: center;
width: 20px;
} }
File moved
File moved
File moved
File moved
File moved
/**********************************************************************************
* The global ajax_ordernumber object should have the following entries:
* - Translations:
* ORDERNUMBER_JS_NOT_AUTHORIZED, ORDERNUMBER_JS_INVALID_COUNTERVALUE, ORDERNUMBER_JS_JSONERROR
* ORDERNUMBER_JS_NEWCOUNTER, ORDERNUMBER_JS_EDITCOUNTER, ORDERNUMBER_JS_DELETECOUNTER
* ORDERNUMBER_JS_ADD_FAILED, ORDERNUMBER_JS_MODIFY_FAILED, ORDERNUMBER_JS_DELETE_FAILED
* - ajax_url: The URL for all AJAX calls
* Optional entries (callback functions) are:
* - updateMessages(messages, cssidentifier)
* - parseAjaxResponse(response) => return json
* - modifyAjaxArgs(ajaxargs) => return ajaxargs with modified arguments for jquery.ajax calls
*/
/**********************************************************************************
*
* Javascript for the counter modification table
*
**********************************************************************************/
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).closest("tr.counter_row");
return { row: row };
}
var handleJSONResponse = function (json, counter) {
if ('updateMessages' in ajax_ordernumber) {
ajax_ordernumber.updateMessages(json['messages'], "ordernumber");
}
if (!json.authorized && !json.success) {
alert(ajax_ordernumber.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.ORDERNUMBER_JS_EDITCOUNTER, msgprefix, counter.counter, counter.value), counter.value);
if (value != null)
value = parseInt(value);
if (isNaN(value))
msgprefix = ajax_ordernumber.ORDERNUMBER_JS_INVALID_COUNTERVALUE;
}
if (value != null) {
var loading = jQuery("img.ordernumber-loading").first().clone().insertAfter(btn).show();
var ajaxargs = {
type: "POST",
url: ajax_ordernumber.ajax_url,
data: {
action: 'setCounter',
nrtype: counter.type,
counter: counter.counter,
value: value
},
success: function ( json ) {
try {
if ('parseAjaxResponse' in ajax_ordernumber) {
json = ajax_ordernumber.parseAjaxResponse(json);
}
handleJSONResponse(json, counter);
} catch (e) {
alert(ajax_ordernumber.ORDERNUMBER_JS_JSONERROR+"\n"+e);
return;
}
if (json.success>0) {
// replace the whole row with the html returned by the AJAX call:
jQuery(counter.row).replaceWith(json.row);
// jQuery(counter.row).find(".counter_value").text(value);
} else {
alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_MODIFY_FAILED, counter.counter));
}
},
error: function() { alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_MODIFY_FAILED, counter.counter)); },
complete: function() { jQuery(loading).remove(); },
};
if ('modifyAjaxArgs' in ajax_ordernumber) {
ajaxargs = ajax_ordernumber.modifyAjaxArgs(ajaxargs);
}
jQuery.ajax(ajaxargs);
}
}
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.ORDERNUMBER_JS_DELETECOUNTER, counter.counter, counter.value));
if (proceed == true) {
var loading = jQuery("img.ordernumber-loading").first().clone().insertAfter(btn).show();
var ajaxargs = {
type: "POST",
dataType: "json",
url: ajax_ordernumber.ajax_url,
data: {
action: 'deleteCounter',
nrtype: counter.type,
counter: counter.counter
},
success: function ( json ) {
try {
if ('parseAjaxResponse' in ajax_ordernumber) {
json = ajax_ordernumber.parseAjaxResponse(json);
}
handleJSONResponse(json, counter);
} catch (e) {
alert(ajax_ordernumber.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.ORDERNUMBER_JS_DELETE_FAILED, counter.counter));
}
},
error: function() { alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_DELETE_FAILED, counter.counter)); },
complete: function() { jQuery(loading).remove(); },
};
if ('modifyAjaxArgs' in ajax_ordernumber) {
ajaxargs = ajax_ordernumber.modifyAjaxArgs(ajaxargs);
}
jQuery.ajax(ajaxargs);
}
}
var ajaxAddCounter = function (btn, nrtype) {
var row = jQuery(btn).parents("tr.addcounter_row");
var countername = prompt (ajax_ordernumber.ORDERNUMBER_JS_NEWCOUNTER);
if (countername != null) {
var loading = jQuery("img.ordernumber-loading").first().clone().insertAfter(jQuery(btn).find("img.ordernumber-counter-addbtn")).show();
var ajaxargs = {
type: "POST",
dataType: "json",
url: ajax_ordernumber.ajax_url,
data: {
action: "addCounter",
nrtype: nrtype,
counter: countername
},
success: function ( json ) {
try {
if ('parseAjaxResponse' in ajax_ordernumber) {
json = ajax_ordernumber.parseAjaxResponse(json);
}
handleJSONResponse(json, null);
} catch (e) {
alert(ajax_ordernumber.ORDERNUMBER_JS_JSONERROR+"\n"+e);
return;
}
if (json.success>0) {
if (json.row) {
jQuery(row).before(jQuery(json.row));
}
} else {
alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_ADD_FAILED, countername));
}
},
error: function() { alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_ADD_FAILED, countername)); },
complete: function() { jQuery(loading).remove(); },
};
// console.log("Ajaxargs", ajaxargs);
if ('modifyAjaxArgs' in ajax_ordernumber) {
ajaxargs = ajax_ordernumber.modifyAjaxArgs(ajaxargs);
}
jQuery.ajax(ajaxargs);
}
}
/**********************************************************************************
*
* Javascript for the Custom Variables table
*
**********************************************************************************/
var ordernumberVariablesAddRow = function (template, element) {
var cl = jQuery("#" + template + " tr").clone(true);
// Enable all form controls
jQuery(cl).find('input,select,button,img').removeAttr('disabled');
if (jQuery.fn.chosen) {
// select boxes handled by the chosen juery plugin cannot simply be cloned,
// instead we need to re-initialize chosen!
jQuery(cl).find('select').removeClass("chzn-done").removeAttr("id").css("display", "block").next().remove();
jQuery(cl).find('select').chosen({width: "50px"});
}
// Now insert this new row into the table
jQuery(cl).appendTo("table#" + element + " tbody");
jQuery("tr#ordernumber-replacements-empty-row")
.addClass("rowhidden")
.find('input')
.attr('disabled', 'disabled');
}
jQuery(document).ready (function () {
jQuery('img.ordernumber-replacement-deletebtn').click(
function () {
var count = jQuery(this).closest('table').find('tbody tr').length;
if (count<=1) {
jQuery("tr#ordernumber-replacements-empty-row")
.removeClass("rowhidden")
.find('input,select,button,img')
.removeAttr('disabled');
}
jQuery(this).closest('tr').remove();
}
);
jQuery("#ordernumber_variables tbody").sortable();
});
This diff is collapsed.
<?php
/**
* Advanced Ordernumbers generic helper class for WooCommerce
* Reinhold Kainhofer, Open Tools, office@open-tools.net
* @copyright (C) 2012-2015 - Reinhold Kainhofer
* @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
**/
if ( !defined( 'ABSPATH' ) ) {
die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' );
}
if (!class_exists( 'OrdernumberHelper' ))
require_once (dirname(__FILE__) . '/library/ordernumber_helper.php');
class OrdernumberHelperWooCommerce extends OrdernumberHelper {
public static $ordernumber_counter_prefix = '_ordernumber_counter_';
function __construct() {
parent::__construct();
load_plugin_textdomain('opentools-ordernumbers', false, basename( dirname( __FILE__ ) ) . '/languages' );
// WC-specific Defaults for the HTML tables
$this->_styles['counter-table-class'] = "widefat";
$this->_styles['variable-table-class'] = "widefat wc_input_table sortable";
}
static function getHelper() {
static $helper = null;
if (!$helper) {
$helper = new OrdernumberHelperWooCommerce();
}
return $helper;
}
/**
* HELPER FUNCTIONS, WooCommerce-specific
*/
public function __($string) {
$string = $this->readableString($string);
return __($string, 'opentools-advanced-ordernumbers');
}
function urlPath($type, $file) {
return plugins_url('library/' . $type . '/' . $file, __FILE__);
}
public function print_admin_styles() {
wp_register_style('ordernumber-styles', $this->urlPath('css', 'ordernumber.css'));
wp_enqueue_style('ordernumber-styles');
}
public function print_admin_scripts() {
wp_register_script( 'ordernumber-script', $this->urlPath('js', 'ordernumber.js', __FILE__), array('jquery') );
wp_enqueue_script( 'ordernumber-script');
// Handle the translations:
$localizations = array( 'ajax_url' => admin_url( 'admin-ajax.php' ) );
$localizations['ORDERNUMBER_JS_JSONERROR'] = $this->__("Error reading response from server:");
$localizations['ORDERNUMBER_JS_NOT_AUTHORIZED'] = $this->__("You are not authorized to modify order number counters.");
$localizations['ORDERNUMBER_JS_NEWCOUNTER'] = $this->__("Please enter the format/name of the new counter:");
$localizations['ORDERNUMBER_JS_ADD_FAILED'] = $this->__("Failed adding counter {0}");
$localizations['ORDERNUMBER_JS_INVALID_COUNTERVALUE'] = $this->__("You entered an invalid value for the counter.\n\n");
$localizations['ORDERNUMBER_JS_EDITCOUNTER'] = $this->__("{0}Please enter the new value for the counter '{1}' (current value: {2}):");
$localizations['ORDERNUMBER_JS_MODIFY_FAILED'] = $this->__("Failed modifying counter {0}");
$localizations['ORDERNUMBER_JS_DELETECOUNTER'] = $this->__("Really delete counter '{0}' with value '{1}'?");
$localizations['ORDERNUMBER_JS_DELETE_FAILED'] = $this->__("Failed deleting counter {0}");
// in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.we_value
wp_localize_script( 'ordernumber-script', 'ajax_ordernumber', $localizations );
}
function getAllCounters($type) {
$counters = array();
$pfxlen = strlen(self::$ordernumber_counter_prefix );
foreach (wp_load_alloptions() as $name => $value) {
if (substr($name, 0, $pfxlen) == self::$ordernumber_counter_prefix) {
$parts = explode('-', substr($name, $pfxlen), 2);
if (sizeof($parts)==1) {
array_unshift($parts, 'ordernumber');
}
// print("<h1>$type Counter: $name with value $value encountered, prefix=".self::$ordernumber_counter_prefix.", parts=".print_r($parts,1)."</h1>");
if ($parts[0]==$type) {
$counters[] = array(
'type' => $parts[0],
'name' => $parts[1],
'value' => $value,
);
}
}
}
return $counters;
}
function getCounter($type, $format, $default=0) {
return get_option (self::$ordernumber_counter_prefix.$type.'-'.$format, $default);
}
function addCounter($type, $format, $value) {
return $this->setCounter($type, $format, $value);
}
function setCounter($type, $format, $value) {
return update_option(self::$ordernumber_counter_prefix.$type.'-'.$format, $value);
}
function deleteCounter($type, $format) {
return delete_option(self::$ordernumber_counter_prefix.$type.'-'.$format);
}
}
<?php
/**
* This is the actual ordernumber plugin class for WooCommerce.
* Copyright (C) 2015 Reinhold Kainhofer, Open Tools
* Author: Open Tools, Reinhold Kainhofer
* Author URI: http://open-tools.net
* License: GPL2+
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class OpenToolsOrdernumbers {
public $ordernumber_meta = "_oton_number_";
public $ordernumber_new_placeholder = "[New Order]";
protected $helper = null;
protected $settings = array();
/**
* Construct the plugin object
*/
public function __construct()
{
$this->helper = OrdernumberHelperWooCommerce::getHelper();
$this->initializeSettings();
$this->initializeHooks();
$this->helper->registerCallback('setupStoreReplacements', array($this, 'setupStoreReplacements'));
$this->helper->registerCallback('setupOrderReplacements', array($this, 'setupOrderReplacements'));
$this->helper->registerCallback('setupUserReplacements', array($this, 'setupUserReplacements'));
$this->helper->registerCallback('setupShippingReplacements', array($this, 'setupShippingReplacements'));
$this->helper->registerCallback('setupThirdPartyReplacements', array($this, 'setupThirdPartyReplacements'));
}
/**
* Install all neccessary filters and actions for this plugin
*/
protected function initializeHooks() {
$helper = OrdernumberHelperWooCommerce::getHelper();
// 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_admin_field_ordernumber_counters', array( $this, 'admin_field_counters' ) );
add_action( 'woocommerce_admin_field_ordernumber_variables', array( $this, 'admin_field_variables' ) );
add_action( 'pre_update_option_ordernumber_variables', array( $this, 'update_option_variables'));
add_action( 'woocommerce_order_actions', array( $this, 'add_order_action_new_number' ) );
add_action( 'woocommerce_order_action_assign_new_ordernumber', array( $this, 'order_action_assign_new_ordernumber' ) );
add_action( 'admin_print_styles-woocommerce_page_wc-settings', array($helper, 'print_admin_styles'));
add_action( 'admin_print_scripts-woocommerce_page_wc-settings', array($this, 'print_admin_scripts'));
// AJAX counter modifications
add_action( 'wp_ajax_setCounter', array($this, 'counter_set_callback') );
add_action( 'wp_ajax_addCounter', array($this, 'counter_add_callback') );
add_action( 'wp_ajax_deleteCounter', 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
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_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! */);
}
/**
* Setup all options and the corresponding settings UI to configure this plugin, using the WP settings API
*/
protected function initializeSettings() {
// Init settings
$this->settings = array(
array(
'name' => $this->helper->__( 'Advanced Order Numbers'),
'desc' => $this->helper->__( 'Configure the format and the counters of the order numbers in WooCommerce.'),
'type' => 'title',
'id' => 'ordernumber_options'
),
array(
'name' => $this->helper->__( 'Customize Order Numbers'),
'desc' => $this->helper->__( 'Check to use custom order numbers rather than the default wordpress post ID.'),
'id' => 'customize_ordernumber',
'type' => 'checkbox',
'default' => 'no'
),
array(
'title' => $this->helper->__( 'Order number format'),
'desc' => $this->helper->__( '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' => $this->helper->__( 'Use global counter'),
'desc' => $this->helper->__( '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(
'name' => $this->helper->__( 'All order number counters'),
'desc' => $this->helper->__( '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',
'nrtype' => 'ordernumber',
),
array( 'type' => 'sectionend', 'id' => 'ordernumber_options' ),
// TODO: customize order password, and other numbers!
array(
'name' => $this->helper->__( 'Custom Variables'),
'desc' => $this->helper->__( 'Define your own (conditional) variables for use in the number formats'),
'type' => 'title',
'id' => 'ordernumber_variables'
),
array(
'id' => 'ordernumber_variables',
'type' => 'ordernumber_variables',
),
array( 'type' => 'sectionend', 'id' => 'ordernumber_variables' ),
array(
'name' => $this->helper->__( 'Current Counters'),
'type' => 'title',
'id' => 'ordernumber_counters'
),
array( 'type' => 'sectionend', 'id' => 'ordernumber_counters' ),
);
// Default options
add_option ('customize_ordernumber', 'no');
add_option ('ordernumber_format', "#");
add_option ('ordernumber_global', 'no');
add_option ('ordernumber_variables', array());
}
/**
* Insert our own section in the checkout setting page. Rearrange the sections array to make sure our settings
* come second place, directly after the default page with the '' key and before all the payment gateways
*/
function add_admin_section($sections) {
$newsections = array();
foreach ($sections as $sec => $name ) {
$newsections[$sec] = $name;
if ($sec == '') {
$newsections['ordernumber'] = $this->helper->__('Order Numbers');
}
}
return $newsections;
}
public function settings_output() {
global $current_section;
if ($current_section == 'ordernumber') {
$settings = $this->settings;
WC_Admin_Settings::output_fields( $settings );
}
}
public function settings_save() {
global $current_section;
if ($current_section == 'ordernumber') {
$settings = $this->settings;
WC_Admin_Settings::save_fields( $settings );
}
}
/**
* 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() {
$this->helper->print_admin_scripts();
wp_register_script( 'ordernumber-admin', plugins_url('assets/js/ordernumber-config.js', __FILE__), array('jquery'));
wp_enqueue_script( 'ordernumber-admin');
}
/**
* Render the Custom Variables configuration table
*/
public function admin_field_variables($settings) {
$variables = get_option( $settings['id'], array() );
if (!is_array($variables)) {
$variables = array();
} ?>
<tr valign="top">
<td class="forminp forminp-<?php echo sanitize_title( $settings['type'] ) ?>" colspan="2">
<?php
print $this->helper->custom_variables_create_table($settings['id'], $variables);
?>
</td>
</tr>
<?php
}
/**
* Store the variable replacements array into the options. Need to transpose the array before we can store it into the options...
* This filter is called directly before the option is saved.
*/
public function update_option_variables ($value) {
return OrdernumberHelper::transposeCustomVariables($value);
}
/**
* Render the Counter Values modification table
*/
public function admin_field_counters ($settings) {
// Description handling
$field_description = WC_Admin_Settings::get_field_description( $settings );
extract( $field_description );
?>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="<?php echo esc_attr( $settings['id'] ); ?>"><?php echo esc_html( $settings['title'] ); ?></label>
<?php echo $tooltip_html; ?>
</th>
<td class="forminp forminp-<?php echo sanitize_title( $settings['nrtype'] ) ?>">
<?php
$counters = $this->helper->getAllCounters($settings['nrtype']);
echo $this->helper->counter_modification_create_table($settings['nrtype'], $counters);
?>
</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)
*/
public function order_search_fields($fields) {
$fields[] = $this->ordernumber_meta;
return $fields;
}
/**
* Sort the order list's "Order" column by our post meta rather than by ID
*/
public function modify_order_column_sortkey($columns) {
$columns['order_title'] = $this->ordernumber_meta;
return $columns;
}
/**
* Add the "create new order number" action to the edit order page in the Backend
*/
public function add_order_action_new_number($actions) {
$actions['assign_new_ordernumber'] = $this->helper->__('Assign a new order number');
return $actions;
}
/**
* 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->generateNumber($order->id, $order, 'ordernumber');
}
/**
* Handle new posts created in the frontend. This action will be called for all posts,
* 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_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') {
return;
} else {
// Handle new admin-created orders, where the address is entered later on!
// Assign an order number:
$number = $this->assign_new_ordernumber($post_id, $post, $update);
}
}
/**
* AJAX Counter handling (simple loading/storing counters), storing them as options
*/
public function counter_delete_callback() {
$json = array('action' => 'delete_counter', 'success' => 0);
$json['success'] = $this->helper->deleteCounter($_POST['nrtype'], $_POST['counter']);
wp_send_json($json);
}
public function counter_add_callback () {
$type = $_POST['nrtype'];
$format = $_POST['counter'];
$value = isset($_POST['value'])?$_POST['value']:"0";
$json = array('action' => 'add_counter', 'success' => 0);
if ($this->helper->getCounter($type, $format, -1) != -1) {
// Counter already exists => error message
$json['error'] = sprintf($this->helper->__('Counter "%s" already exists, cannot create again.'), $format);
} else {
$json['success'] = $this->helper->setCounter($type, $format, $value);
$json['row'] = $this->helper->counter_modification_create_row($type, $format, $value);
}
wp_send_json($json);
}
public function counter_set_callback () {
$json = array('action' => 'set_counter', 'success' => 0);
$json['success'] = $this->helper->setCounter($_POST['nrtype'], $_POST['counter'], $_POST['value']);
$json['row'] = $this->helper->counter_modification_create_row($_POST['nrtype'], $_POST['counter'], $_POST['value']);
wp_send_json($json);
}
/** ***********************************************************
*
* REPLACEMENT FUNCTIONS
*
**************************************************************/
public 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]"] = $address->billing_company;
$reps["[zip]"] = $address->billing_postcode;
$reps["[postcode]"] = $address->billing_postcode;
$reps["[city]"] = $address->billing_city;
$country = $address->billing_country;
$state = $address->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;
}
public function setupStoreReplacements (&$reps, $order, $nrtype) {
}
public function setupOrderReplacements (&$reps, $order, $nrtype) {
$reps["[orderid]"] = $order->id;
if ($nrtype != 'ordernumber') {
$reps["[ordernumber]"] = $order->get_order_number();
}
$reps["[orderstatus]"] = $order->get_status();
$reps["[currency]"] = $order->get_order_currency();
$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();
$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();
// List-valued properties for custom variable checks:
// TODO: Also implement variable for:
// - Shipping needed
// - Downloads available
$lineitems = $order->get_items();
$skus = array();
$categories = array();
$tags = array();
$shippingclasses = array();
foreach ($lineitems as $l) {
$p = $order->get_product_from_item($l);
$skus[$p->get_sku()] = 1;
foreach (wc_get_product_terms( $p->id, 'product_cat') as $c) {
$categories[$c->slug] = 1;
}
foreach (wc_get_product_terms( $p->id, 'product_tag') as $c) {
$tags[$c->slug] = 1;
}
$shippingclasses[$p->get_shipping_class()] = 1;
}
$reps["[skus]"] = array_keys($skus);
$reps["[categories]"] = array_keys($categories);
$reps["[tags]"] = array_keys($tags);
$reps["[shippingclasses]"] = array_keys($shippingclasses);
}
public function setupUserReplacements (&$reps, $details, $nrtype) {
$reps["[ipaddress]"] = $details->customer_ip_address;
$reps["[userid]"] = $details->get_user_id();
}
public function setupShippingReplacements(&$reps, $order, $nrtype) {
// $reps["[shippingmethod]"] = $order->getShippingMethod();
}
/*public function setupInvoiceReplacements (&$reps, $invoice, $order, $nrtype) {
$reps["[invoiceid]"] = $invoice->getId();
}*/
public function setupThirdPartyReplacements (&$reps, $details, $nrtype) {
$reps = apply_filters( 'opentools_ordernumber_replacements', $reps, $details, $nrtype);
}
function generateNumber($orderid, $order, $type='ordernumber') {
if (get_option('customize_'.$type, 'no')!='no') {
$fmt = get_option ($type.'_format', "#");
$ctrsettings = array(
"${type}_format" => '',
"${type}_counter" => '',
"${type}_global" => get_option ($type.'_global', 'no'),
"${type}_padding" => 1,
"${type}_step" => 1,
"${type}_start" => 1,
);
$customvars = get_option ('ordernumber_variables', array());
$number = $this->helper->createNumber ($fmt, $type, $order, $customvars, $ctrsettings);
update_post_meta( $orderid, $this->ordernumber_meta.$type, $number );
return $number;
} else {
return $orderid;
}
}
/**
* The hook to assign a customized order number (unless the order already has one assigned)
*/
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.'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.'ordernumber', 'true');
if ($number == $this->ordernumber_new_placeholder && $order->post_status != 'auto-draft') {
$number = $this->generateNumber($orderid, $order, 'ordernumber');
// Assign a new number
}
return $number;
}
/**
* The generic function to retrieve a particular number
*/
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, $type);
} elseif (!empty($stored_number)) {
// Order number already exists => simply return it
return $stored_number;
} else {
// No order number was created for this order, so simply use the orderid as default.
return $orderid;
}
}
/**
* Callback function for Woocommerce to retrieve the ordernumber for an order
*/
function get_ordernumber($orderid, $order) {
return $this->get_number($orderid, $order);
}
}
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment