From 7a0dba2b21d97f621274449fd41b10bbbf8d92ae Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Fri, 3 Jul 2015 12:39:22 +0200
Subject: [PATCH] Library: Start moving to ordernumber library...

---
 .../OpenTools/Ordernumber/Helper/Data.php     |   7 +-
 .../OpenTools/Ordernumber/Model/Observer.php  |   2 +
 .../OpenTools/Ordernumber/etc/config.xml      |   2 +-
 .../{install-0.1.0.php => install-1.0.0.php}  |   0
 .../upgrade-1.0.0-1.1.0.php                   |  45 ++
 .../Ordernumber/library/css/index.html        |   1 +
 .../Ordernumber/library/css/ordernumber.css   | 110 ++++
 .../library/images/icon-16-delete.png         | Bin 0 -> 555 bytes
 .../library/images/icon-16-edit.png           | Bin 0 -> 623 bytes
 .../library/images/icon-16-new.png            | Bin 0 -> 430 bytes
 .../Ordernumber/library/images/index.html     |   1 +
 .../Ordernumber/library/images/loading.gif    | Bin 0 -> 2211 bytes
 .../Ordernumber/library/images/loading.png    | Bin 0 -> 18117 bytes
 lib/OpenTools/Ordernumber/library/index.html  |   1 +
 .../Ordernumber/library/js/index.html         |   1 +
 .../Ordernumber/library/js/ordernumber.js     | 225 +++++++
 .../library/ordernumber_helper.php            | 567 ++++++++++++++++++
 .../ordernumber_helper_magento.php            | 113 ++++
 18 files changed, 1073 insertions(+), 2 deletions(-)
 rename app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/{install-0.1.0.php => install-1.0.0.php} (100%)
 create mode 100644 app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/upgrade-1.0.0-1.1.0.php
 create mode 100644 lib/OpenTools/Ordernumber/library/css/index.html
 create mode 100644 lib/OpenTools/Ordernumber/library/css/ordernumber.css
 create mode 100644 lib/OpenTools/Ordernumber/library/images/icon-16-delete.png
 create mode 100644 lib/OpenTools/Ordernumber/library/images/icon-16-edit.png
 create mode 100644 lib/OpenTools/Ordernumber/library/images/icon-16-new.png
 create mode 100644 lib/OpenTools/Ordernumber/library/images/index.html
 create mode 100644 lib/OpenTools/Ordernumber/library/images/loading.gif
 create mode 100644 lib/OpenTools/Ordernumber/library/images/loading.png
 create mode 100644 lib/OpenTools/Ordernumber/library/index.html
 create mode 100644 lib/OpenTools/Ordernumber/library/js/index.html
 create mode 100644 lib/OpenTools/Ordernumber/library/js/ordernumber.js
 create mode 100644 lib/OpenTools/Ordernumber/library/ordernumber_helper.php
 create mode 100644 lib/OpenTools/Ordernumber/ordernumber_helper_magento.php

diff --git a/app/code/community/OpenTools/Ordernumber/Helper/Data.php b/app/code/community/OpenTools/Ordernumber/Helper/Data.php
index 026b997..b059a83 100644
--- a/app/code/community/OpenTools/Ordernumber/Helper/Data.php
+++ b/app/code/community/OpenTools/Ordernumber/Helper/Data.php
@@ -1,8 +1,13 @@
 <?php
+require_once(Mage::getBaseDir('lib') . '/OpenTools/Ordernumber/ordernumber_helper_magento.php');
+
 class OpenTools_Ordernumber_Helper_Data extends Mage_Core_Helper_Abstract
 {
-    public function logitem($label, $item)
+	protected $helper = null;
+	
+    function __construct($label, $item)
     {
+        $this->helper = OrdernumberHelperMagento::getHelper();
         Mage::Log($label . " " . get_class($item) . "\n", null, 'ordernumber.log');
         Mage::Log(is_array($item)?$item:$item->debug(), null, 'ordernumber.log');
         Mage::Log(get_class_methods(get_class($item)), null, 'ordernumber.log');
diff --git a/app/code/community/OpenTools/Ordernumber/Model/Observer.php b/app/code/community/OpenTools/Ordernumber/Model/Observer.php
index 295d637..165cb3f 100644
--- a/app/code/community/OpenTools/Ordernumber/Model/Observer.php
+++ b/app/code/community/OpenTools/Ordernumber/Model/Observer.php
@@ -20,9 +20,11 @@
  * @copyright  Copyright (c) 2010 Fooman Limited (http://www.fooman.co.nz)
  * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  */
+
 class OpenTools_Ordernumber_Model_Observer extends Mage_Core_Model_Abstract
 {
     protected $_dbModel = null;
+
     protected function _getModel()
     {
         return Mage::getModel('opentools_ordernumber/ordernumber');
diff --git a/app/code/community/OpenTools/Ordernumber/etc/config.xml b/app/code/community/OpenTools/Ordernumber/etc/config.xml
index ec634d3..4513c1d 100644
--- a/app/code/community/OpenTools/Ordernumber/etc/config.xml
+++ b/app/code/community/OpenTools/Ordernumber/etc/config.xml
@@ -4,7 +4,7 @@
 <!-- declare module's version information -->
         <OpenTools_Ordernumber>
 <!-- this version number will be used for database upgrades -->
-            <version>0.1.0</version>
+            <version>1.0.0</version>
             <depends>
                 <Mage_Sales />
             </depends>
diff --git a/app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/install-0.1.0.php b/app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/install-1.0.0.php
similarity index 100%
rename from app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/install-0.1.0.php
rename to app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/install-1.0.0.php
diff --git a/app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/upgrade-1.0.0-1.1.0.php b/app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/upgrade-1.0.0-1.1.0.php
new file mode 100644
index 0000000..d00a87b
--- /dev/null
+++ b/app/code/community/OpenTools/Ordernumber/sql/opentools_ordernumber_setup/upgrade-1.0.0-1.1.0.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Ordernmber upgrade script
+ * @author OpenTools
+ */
+/**
+ * @var $installer Mage_Core_Model_Resource_Setup
+ */
+$installer = $this;
+
+/**
+ * Create table opentools_ordernumber
+ */
+$connection = $installer->getConnection();
+$tablename = $installer->getTable('opentools_ordernumber/ordernumber');
+
+if (!$connection->isTableExists($tablename)) {
+
+	$table = $connection
+		->newTable($tablename)
+		->addColumn('ordernumber_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
+			'unsigned' => true,
+			'identity' => true,
+			'nullable' => false,
+			'primary'  => true,
+		), 'Ordernumber id')
+		->addColumn('number_type',   Varien_Db_Ddl_Table::TYPE_TEXT,      63, array('nullable'=> false),                  'Number Type')
+		->addColumn('number_scope',  Varien_Db_Ddl_Table::TYPE_TEXT,      20, array('nullable'=> true, 'default'=>''),    'Number Scope')
+		->addColumn('number_format', Varien_Db_Ddl_Table::TYPE_TEXT,     255, array('nullable'=> true, 'default'=>''),    'Number Format')
+		->addColumn('count',         Varien_Db_Ddl_Table::TYPE_INTEGER, null, array('unsigned'=>true, 'nullable'=>false), 'Counter')
+		->addIndex($installer->getIdxName(
+				$tablename,
+				array('number_type', 'number_scope', 'number_format'),
+				Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
+			),
+			array('number_type', 'number_scope', 'number_format'),
+			array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)
+		)
+		->setComment('Ordernumber Counter Table');
+	// TODO: drop table if exists!
+	$installer->getConnection()->createTable($table);
+} else {
+	// Table already exists, don't do anything (but also don't try to create the table again)
+}
+die()
\ No newline at end of file
diff --git a/lib/OpenTools/Ordernumber/library/css/index.html b/lib/OpenTools/Ordernumber/library/css/index.html
new file mode 100644
index 0000000..2efb97f
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/css/index.html
@@ -0,0 +1 @@
+<!DOCTYPE html><title></title>
diff --git a/lib/OpenTools/Ordernumber/library/css/ordernumber.css b/lib/OpenTools/Ordernumber/library/css/ordernumber.css
new file mode 100644
index 0000000..f6e0862
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/css/ordernumber.css
@@ -0,0 +1,110 @@
+
+table.ordernumber-countertable {
+    border: 1px solid #888888;
+    display: inline-table;
+}
+
+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 {
+    border: 1px solid #888888;
+	width: inherit;
+}
+
+table.ordernumber_variables td, table.ordernumber_variables th {
+    padding: 0px;
+	vertical-align: middle;
+}
+/* table.ordernumber_variables td.sort:before { */
+/*     float: none; */
+/* 	display: inline-block; */
+/* } */
+
+table.ordernumber_variables thead th {
+    text-align: center;
+	width: auto;
+}
+td.counter_value {
+    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 tfoot > tr.addreplacement_row > td {
+    background: #E0E0E0;
+}
+table.ordernumber_variables tbody > tr:nth-child(even) > td {
+    background: #F0F0F0;
+}
+table.ordernumber_variables tbody tr td input {
+	width: 100%;
+}
+.ordernumber-btn {
+    cursor: pointer;
+}
+
+table.ordernumber_variables img {
+    padding: 0;
+    margin: 0;    
+}
+tr.rowhidden {
+	display: none;
+}
+
+/* Adjust the columns of the replacements table */
+col.variables_ifvar, col.variables_ifval {
+	width: 15%;
+}
+col.variables_ifop {
+	width: 10%;
+}
+col.variables_thenvar, col.variables_thenval {
+	width: 25%;
+}
+.variables_then, .variables_settings {
+	text-align: center;
+	width: 20px;
+}
+
+
+
diff --git a/lib/OpenTools/Ordernumber/library/images/icon-16-delete.png b/lib/OpenTools/Ordernumber/library/images/icon-16-delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..1573413858f535fc32cb0428d3275f639a5f74cc
GIT binary patch
literal 555
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7KY6-1hE&8YoxI;WI#8l*
zzI3yKps>q9$193nEga?=9o=a~Tvx1it>~ES{m{?KRG~?!to+oY2UiwotZ=^d|A2gl
z_rk4QtP7=@rJA1Y+iN-D$t5pw`5zDFy#G-5yym^-@kvLbIX<{GF-%K+=-zpRW!>+-
zqMgUND=JS`f4q7+b<OG1Hf$4E{)w4bNL>6-;J0#$iM_sM-<BO3y1Jgm#z8j!Vr6Bw
z?RPk!zigqRdwl$)0*Q0y6U)W7ZBI;RpEp0TYFGQQV{@XS-`3ksuoLXPWn=5Ok>l;#
z0KM4@_RHV8l~61!C#MwmZnOV#uk(Vvy`IIzmku<9Xq<Rpp%$K862jHKG{7S(Yu1YG
z4|bX9>K0UUFBOuJONxkZ@8#u5PcJA6GTc&SwEJ3<xo4HT3G10fj}IJVWLWm$ukDhc
zy24bOXZi&>Wqhq?lr~EA^aLE8v1?OO%T<k?@A`MK@7=rY*zu*UtSdJM@7gu#;g^tG
zw}N^XDryQ`P<|m^^I<=;NcYn%dvba%-I}#!yLxG<=h?GHKXbzFeU<#^f5E)t$9>1A
zRhMLB9m~zvtUGii<nH7WDK&M?s?YZw7%v5$_<f)8+Sjk*dU|O$?|+{iDlHznUF+PD
zhmTj!Ke=n?$%>{H^%MVe_ccFuuaIw#{PX9%wYG%MG{wjUj`a$i_V4?GQ?{-8(8IvM
Oz~JfX=d#Wzp$Pz#?g57Y

literal 0
HcmV?d00001

diff --git a/lib/OpenTools/Ordernumber/library/images/icon-16-edit.png b/lib/OpenTools/Ordernumber/library/images/icon-16-edit.png
new file mode 100644
index 0000000000000000000000000000000000000000..b1bcf04bb12fe3186243c8becb73bb0b24795117
GIT binary patch
literal 623
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7BuiW)N`mv#O3D+9QW+dm
z@{>{(JaZG%Q-e|yQz{EjrrIztFbR6PIEGZ*>Y41Df7wBxEq(81Pv_efdV(@Rr`%_6
zQ49R}gF9r&ogIt1`U@V~fAF^`cyK^7R9nEran*yaBdi(RD^%H+2;9=}mAPG-bNpVa
za0|=SODTP;E1%u1OmEY%^*g*mu!t}4$Yv*w`_K2dax$idSWNgJk$f|H=b7EozwT(O
zsE8IZS{U{0*f8g;$a3LA*(F9V0`C0z_II0+(i;8eM%gQmEP2PqSa2{gOUdl~gjJ^u
zEW8Ts?uUn!>T@&(vYzR?t&#hF-Hmnom(Sr)PD?qz`nieeYtK|S&4_i^Z``=IH`@HI
z(WxX0j=lh^>HFvC`DJIFn|?~L>q60*XS3&?`pbM<(|zK%;z9u(-e}wUsOT@wd@L4!
zvfi2Be|PnrtkvD#ju0`U=`#8knp69yf4W)nG0CWM>E*8r9-A!8laYA8x@_UoL$Bkc
zFC2gPU;ay)RC3O@w6cX3i;u3q7Hw*<c9qE)Lp$>q%!fncjGo4SiD=Bbk^0j3R#%(*
z^?f1R4t(a}V9l=2^|vvx`NYJ2<8D1)%Yy5{w<dq&h`n>?S3udD`43u;+%Y`Ht?M7@
zZd7qaqJY6vX`0>&FURie4}mYvuReP!*w`l2sCJ5hec{C?UcxWaX5>WwuH8QIh?S{-
ztqRM-DIE*5`;tS>`1q=&*_+-fKe8}Ya$W2qu7^+FZ*RZiP&q5@u1!^1>COH)v%Z@7
f^^dkQFf$k|{;JcQp6kKDz`)??>gTe~DWM4f#=07D

literal 0
HcmV?d00001

diff --git a/lib/OpenTools/Ordernumber/library/images/icon-16-new.png b/lib/OpenTools/Ordernumber/library/images/icon-16-new.png
new file mode 100644
index 0000000000000000000000000000000000000000..fcd6a5a695d6efadc571362896612e17440e9cc1
GIT binary patch
literal 430
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7OFdm2Ln`8qPPX-Cb`)q!
z*I(Y0utPv6h{aD^yHkN9Y@=a9slDP)&ZJb;@W{^Aq~%Ge$%TpvOSr<q>KbALJjJEY
zDyrOj-e;a|7E|Oo^^kbm&Ard(CW<|iP&#B1l;E{e$l#dEx7Vt+yJR-B?m2kLdsf3<
z{@LZT#1v*3FRkjX>6kI+z*<pmgV~iqVW(23X=lCo?ZDVAEmf=RHgBVUL7rJ@z%yx`
z-K$#HZx^tc$9U$c<`K)Buttf>mT)dX*FQ1q<EzR=OR}sb=DK>E+#P(^?bC$tYb%@G
z=1A}P%y#G9ffW}@fA8dN==<Qdz{te$d(827t$p_nbNWsCUgRn#*vVOOUR<)7L5;II
z{=n{k0unlxz6bWDU4LY-_xdy*w-k3BXP@4^m%D-_Cn>QhZxZTm*_Y1bu58y@U2nCn
zk(bL@*nffVpF82)itTL~Msa0cjceZ|e$aV+#X|MNzS&XS7BVd|Ja5dC>RYF+YS>vL
ivrS>y|NqkUjMHSldrBQxbdiC9fx*+&&t;ucLK6VV5U<4m

literal 0
HcmV?d00001

diff --git a/lib/OpenTools/Ordernumber/library/images/index.html b/lib/OpenTools/Ordernumber/library/images/index.html
new file mode 100644
index 0000000..2efb97f
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/images/index.html
@@ -0,0 +1 @@
+<!DOCTYPE html><title></title>
diff --git a/lib/OpenTools/Ordernumber/library/images/loading.gif b/lib/OpenTools/Ordernumber/library/images/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..94da6d80e05ef96d9d7551013d59c22551c0ae1a
GIT binary patch
literal 2211
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

literal 0
HcmV?d00001

diff --git a/lib/OpenTools/Ordernumber/library/images/loading.png b/lib/OpenTools/Ordernumber/library/images/loading.png
new file mode 100644
index 0000000000000000000000000000000000000000..ac0aa90cbc6fde315828934a2494ec1324b8af56
GIT binary patch
literal 18117
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
Bb$<W=

literal 0
HcmV?d00001

diff --git a/lib/OpenTools/Ordernumber/library/index.html b/lib/OpenTools/Ordernumber/library/index.html
new file mode 100644
index 0000000..2efb97f
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/index.html
@@ -0,0 +1 @@
+<!DOCTYPE html><title></title>
diff --git a/lib/OpenTools/Ordernumber/library/js/index.html b/lib/OpenTools/Ordernumber/library/js/index.html
new file mode 100644
index 0000000..2efb97f
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/js/index.html
@@ -0,0 +1 @@
+<!DOCTYPE html><title></title>
diff --git a/lib/OpenTools/Ordernumber/library/js/ordernumber.js b/lib/OpenTools/Ordernumber/library/js/ordernumber.js
new file mode 100644
index 0000000..70c92e4
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/js/ordernumber.js
@@ -0,0 +1,225 @@
+/**********************************************************************************
+ * 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) {
+		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(); },
+        };
+		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 () {
+			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');
+			}
+		}
+	);
+
+	jQuery("#ordernumber_variables tbody").sortable();
+});
diff --git a/lib/OpenTools/Ordernumber/library/ordernumber_helper.php b/lib/OpenTools/Ordernumber/library/ordernumber_helper.php
new file mode 100644
index 0000000..2b504bc
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/library/ordernumber_helper.php
@@ -0,0 +1,567 @@
+<?php
+/**
+ * Advanced Ordernumbers generic helper class (e-commerce system agnostic)
+ * 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' ) && !defined('_JEXEC') ) { 
+	die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' );
+}
+
+class OrdernumberHelper {
+	static $_version = "0.1";
+	protected $_callbacks = array();
+	public $_styles = array(
+		'counter-table-class' => "table-striped",
+		'counter-table-style' => "",
+		'variable-table-class' => "",
+		'variable-table-style' => "",
+	);
+	/**
+	 * An array containing all language keys for the translations used in the JavaScript code.
+	 * Make sure to set those in the ajax_ordernumber JavaScript array!
+	 */
+	public $jstranslations = array(
+		"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",
+		);
+		
+	/**
+	 * The URL to call for AJAX calls
+	 */
+	public $ajax_url = "";
+   
+	function __construct() {
+		// Set up 
+		$this->registerCallback ("setupDateTimeReplacements", array($this, "setupDateTimeReplacements"));
+	}
+	
+	function getStyle($key) {
+		if (isset($this->_styles[$key])) {
+			return $this->_styles[$key];
+		} else {
+			return '';
+		}
+	}
+	/* Callback handling */
+	
+	/**
+	 * Register a callback for one of the known callback hooks. 
+	 * Valid callbacks are (together with their arguments):
+	 *   - translate($string)
+	 *   - getCounter($type, $countername, $default)
+	 *   - setCounter($type, $countername, $value)
+	 *   - setupDateTimeReplacements(&$reps, $details, $nrtype);
+	 *   - setupStoreReplacements(&$reps, $details, $nrtype);
+	 *   - setupOrderReplacements(&$reps, $details, $nrtype);
+	 *   - setupUserReplacements(&$reps, $details, $nrtype);
+	 *   - setupShippingReplacements(&$reps, $details, $nrtype);
+	 *   - setupThirdPartyReplacements(&$reps, $details, $nrtype);
+	 
+	 *   - urlPath($path, $type)
+	 *  @param string $callback 
+	 *     The name of the callback hook (string)
+	 *  @param function $func 
+	 *     The function (usually a member of the plugin object) for the callback
+	 *  @return none
+	 */
+	public function registerCallback($callback, $func) {
+		$this->callbacks[$callback] = $func;
+	}
+	
+	public function __($string) {
+		if (isset($this->callbacks["translate"])) {
+			return $this->callbacks["translate"]($string);
+		} else {
+			return $string;
+		}
+	}
+
+	/**
+	 * Provide human-readable default values for the translatable strings.
+	 * Some systems use the translation key as fallback if no translation is found,
+	 * so we need to convert it to a human-readable value.
+	 */
+	public function readableString($string) {
+		static $readable_strings = array(
+			"PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE"   => 'Counter value',
+			"PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER" => 'Counter name',
+			"PLG_ORDERNUMBER_COUNTERLIST_ADD"            => 'Add new counter',
+			"PLG_ORDERNUMBER_COUNTERLIST_GLOBAL"         => '[Global]',
+			"PLG_ORDERNUMBER_REPL_IFVAR"                 => 'If variable ...',
+			"PLG_ORDERNUMBER_REPL_IFVAL"                 => 'Value',
+			"PLG_ORDERNUMBER_REPL_SETVAR"                => 'Set variable ...',
+			"PLG_ORDERNUMBER_REPL_TOVAL"                 => 'to value ...',
+			"PLG_ORDERNUMBER_REPL_NOCUSTOMVARS"          => 'No custom variables have been defined.',
+			"PLG_ORDERNUMBER_REPL_ADDVAR"                => 'Add new custom variable',
+			"PLG_ORDERNUMBER_REPL_OP_NOCOND"             => 'No condition',
+			"PLG_ORDERNUMBER_REPL_OP_CONTAINS"           => 'contains',
+			"PLG_ORDERNUMBER_REPL_OP_STARTS"             => 'starts with',
+			"PLG_ORDERNUMBER_REPL_OP_ENDS"               => 'ends with'
+		);
+		// Use the human-readable text as default rather than the generic identifier.
+		// Otherwise, one always has to create a language file for every language, as 
+		// the fallback would be the identifier.
+		if (isset($readable_strings[$string]))
+			return $readable_strings[$string];
+		else
+			return $string;
+	}
+
+	public function urlPath($type, $file) {
+		if (isset($this->callbacks['urlPath'])) {
+			return $this->callbacks['urlPath']($type, $file);
+		} else {
+			throw new Exception('No callback defined for urlPath(type, file)!');
+		}
+	}
+	
+	protected function replacementsCallback ($func, &$reps, $details, $nrtype) {
+		if (isset($this->callbacks[$func])) {
+			return $this->callbacks[$func]($reps, $details, $nrtype);
+		}
+	}
+
+	protected function getCounter($type, $countername, $default) {
+		if (isset($this->callbacks['getCounter'])) {
+			return $this->callbacks['getCounter']($type, $countername, $default);
+		} else {
+			throw new Exception('No callback defined for getCounter(type, countername, default)!');
+		}
+	}
+	
+	protected function setCounter($type, $countername, $value) {
+		if (isset($this->callbacks['getCounter'])) {
+			return $this->callbacks['getCounter']($type, $countername, $value);
+		} else {
+			throw new Exception('No callback defined for setCounter(type, countername, value)!');
+		}
+	}
+	
+	public function getAllCounters($type) {
+		if (isset($this->callbacks['getCounter'])) {
+			return $this->callbacks['getCounter']($type);
+		} else {
+			throw new Exception ('No callback defined for getAllCounters(type)!');
+		}
+	}
+	
+	public static function transposeCustomVariables($cvar) {
+		if (is_object($cvar)) 
+			$cvar = (array)$cvar;
+		if (!is_array($cvar))
+			$cvar = array();
+		// The customvars are stored in transposed form (for technical reasons, since there is no trigger 
+		// called when the corresponding form field from the plugin param is saved)
+		$customvars = array();
+        
+		if (!empty($cvar)) {
+			$keys = array_keys($cvar);
+			foreach (array_keys($cvar[$keys[0]]) as $i) {
+				$entry = array();
+				foreach ($keys as $k) {
+					$entry[$k] = $cvar[$k][$i];
+				}
+				$customvars[] = $entry;
+			}
+		}
+		return $customvars;
+	}
+	
+	/* Return a random "string" of the given length taken from the given alphabet */
+	protected static function randomString($alphabet, $len) {
+		$alen = strlen($alphabet);
+		$r = "";
+		for ($n=0; $n<$len; $n++) {
+			$r .= $alphabet[mt_rand(0, $alen-1)];
+		}
+		return $r;
+	}
+
+	protected 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;
+		}
+		return self::randomString ($alphabet, $len);
+	}
+
+	protected function setupDateTimeReplacements (&$reps, $details, $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;
+	}
+
+	protected function setupReplacements($nrtype, $details) {
+		$reps = array();
+		// The following callbacks directly modify the replacements!
+		$this->replacementsCallback("setupDateTimeReplacements", $reps, $details, $nrtype);
+		$this->replacementsCallback("setupStoreReplacements", $reps, $details, $nrtype);
+		$this->replacementsCallback("setupOrderReplacements", $reps, $details, $nrtype);
+		$this->replacementsCallback("setupUserReplacements", $reps, $details, $nrtype);
+		$this->replacementsCallback("setupShippingReplacements", $reps, $details, $nrtype);
+		$this->replacementsCallback("setupThirdPartyReplacements", $reps, $details, $nrtype);
+		return $reps;
+	}
+
+	protected function setupCustomVariables ($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 'nocondition':
+							$match = true; break;
+					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 the user to override the format like any other custom variable:
+	protected function setupNumberFormatString($fmt, $type, $order, $reps) {
+		if (isset($reps['['.$type.'_format]'])) {
+			return $reps['['.$type.'_format]'];
+		} else {
+			return $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);
+		// Only use string-valued variables for replacement (array-valued variables can be used in custom variable definitions!)
+		$reps = array_filter($reps, function($v) { return !is_array($v);} );
+		return str_ireplace (array_keys($reps), array_values($reps), $fmt);
+	}
+	
+	protected function extractCounterSettings ($fmt, $type, $ctrsettings) {
+		// Some e-Commerce systems use 'yes' for true, others use 1 => correct everything to 1
+		if ($ctrsettings["${type}_global"] == 'yes') {
+			$ctrsettings["${type}_global"] = 1;
+		}
+
+		// First, extract all counter settings, i.e. all strings of the form [#####:startval/increment] or [####/increment:startval]
+		$regexp = '%\[(#+)(/([0-9]+))?(:([0-9]+))?(/([0-9]+))?\]%';
+		
+		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]; 
+			}
+			
+			$fmt = preg_replace($regexp, "#", $fmt);
+		}
+		// 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"]==1)?"":$parts[(count($parts)>1)?1:0];
+		
+		return $ctrsettings;
+	}
+
+	/**
+	 * Create a number of given type for the given format. Optionally, custom variable definitions and counter formatting can be passed.
+	 *   @param fmt The Format of the number (containing variables as [variable] and the counter as # or [####:initial/step])
+	 *   @param type The type of the number format, typically order_number, invoice_number, etc. (depending on the e-commerce suite)
+	 *   @param order The e-commerce-suite specific object describing the order. This will simply be passed on to the replacement hooks function for further data extraction during variable setup
+	 *   @param customvars Definitions (conditions and values) for custom variables. An array of arrays with keys conditionvar, conditionop, conditionval, newvar, newval
+	 *   @param ctrsettings Counter formatting defaults (will be overridden by an explicit counter formating variable of [####:initial/step] in the format). Array keys are: $type_format, $type_counter, $type_global, $type_padding, $type_step, $type_start
+	 *   @return A new number for the given format. The incremented counter has been properly stored.
+	 */
+	public 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);
+JFactory::getApplication()->enqueueMessage("<pre>Counter Settings: ".print_r($ctrsettings,1)."</pre>", 'error');
+// JFactory::getApplication()->enqueueMessage("<pre>Replacements for $type:".print_r($reps,1)."</pre>", 'error');
+		// Increment the counter only if the format contains a placeholder for it!
+		if (strpos($ctrsettings["${type}_format"], "#") !== false) {
+			$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"]);
+		} else {
+			$number = $ctrsettings["${type}_format"];
+		}
+		return $number;
+	}
+	
+	
+	/**
+	 * Create the counter modification HTML table
+	 *     @param $type string
+	 *          
+	 *     @param
+	 */
+	public function counter_modification_create_table($type, $counters) {
+        $html=array();
+        $html[] = "<img src='" . $this->urlPath ('images', 'loading.gif') . "' class='ordernumber-loading' />";
+        $html[] = "<table class=\"ordernumber-countertable " . $this->getStyle('counter-table-class') . "\" " . $this->getStyle('counter-table-style') . ">";
+        $html[] = "<thead>";
+        $html[] = "	<tr>";
+        $html[] = "		<th class='counter_format'>" . $this->__ ('PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER')."</th>";
+        $html[] = "		<th class='counter_value'>" . $this->__ ('PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE'). "</th>";
+        $html[] = "		<th class='counter_buttons'></th>";
+        $html[] = "	</tr>";
+        $html[] = "</thead>";
+        $html[] = "	<colgroup><col class='counter_type'><col style=\"text-align: center\" ><col ></colgroup>";
+        $html[] = "<tbody>";
+        foreach ($counters as $c) {
+            $html[] = $this->counter_modification_create_row ($type, $c->name, $c->value);
+        }
+        $html[] = "</tbody>";
+        $html[] = "<tfoot>";
+        $html[] = "	<tr class='addcounter_row'>";
+        $html[] = "		<td colspan=3 class='counter_add'>";
+        $html[] = "			<div class='ordernumber-counter-addbtn ordernumber-btn' onClick='ajaxAddCounter(this, " . json_encode($type).")'>";
+        $html[] = "				<div class='ordernumber-ajax-loading'>";
+        $html[] = "					<img src='" . $this->urlPath('images', 'icon-16-new.png') . "' class='ordernumber-counter-addbtn' />";
+        $html[] = "				</div>" . $this->__('PLG_ORDERNUMBER_COUNTERLIST_ADD');
+        $html[] = "			</div>";
+        $html[] = "		</td>";
+        $html[] = "  </tr>";
+        $html[] = "</tfoot>";
+        $html[] = "</table>";
+        return implode("\n", $html);
+    }
+
+    public function counter_modification_create_row ($type, $counter, $value) {
+		$html=array();
+		$html[] = "	<tr class='counter_row counter_row_$type'>";
+		$html[] = "		<td class='counter_format'>" . (($counter=="")?($this->__ ('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL')):htmlentities($counter)) . "</td>";
+		$html[] = "		<td class='counter_value'>" . htmlentities((string)$value) . "</td>";
+		$html[] = "		<td class='counter_buttons'>";
+		$html[] = "			<div class='ordernumber-ajax-loading'>";
+		$html[] = "				<img src='" . $this->urlPath('images', 'icon-16-edit.png') . "' class='ordernumber-counter-editbtn ordernumber-btn' ";
+		$html[] = "					onClick='ajaxEditCounter(this, " . json_encode($type) . ", ".json_encode($counter).", " . json_encode($value). ")' />";
+		$html[] = "			</div>";
+		$html[] = "			<div class='ordernumber-ajax-loading'>";
+		$html[] = "				<img src='" . $this->urlPath ('images', 'icon-16-delete.png') . "' class='ordernumber-counter-deletebtn ordernumber-btn' ";
+		$html[] = "					onClick='ajaxDeleteCounter(this, ".json_encode($type).", ".json_encode($counter).", " . json_encode($value) . ")' />";
+		$html[] = "			</div>";
+		$html[] = "		</td>";
+		$html[] = "	</tr>";
+		return implode("\n", $html);
+	}
+	
+	/**
+	 * Create the html table (with AJAX) to define and modify custom variable definitions.
+	 * The returned HTML code assumes that the caller properly adds the ordernumber.css 
+	 * and ordernumber.js to the page and loads the jQuery library.
+	 *    @param name string
+	 *        The HTML post/request variable name for the control.
+	 *    @param variables array
+	 *        The current list of custom variable replacements
+	 *
+	 *    @retval string
+	 *        The HTML code for the custom variable definition table.
+	 */
+    public function custom_variables_create_table($name, $variables) {
+        $html=array();
+//         $html[] = "<pre>Variables: ".print_r($variables,1)."</pre>";
+        $html[] = '<table id="ordernumber_variables_template" style="display:none">';
+        $html[] = $this->custom_variables_create_row($name, array(), 'disabled');
+        $html[] = '</table>';
+        
+        $html[] = '<table id="ordernumber_variables" class="ordernumber_variables ' . $this->getStyle('variable-table-class') . '" cellspacing="0" ' . $this->getStyle('variable-table-style') . '>';
+        $columns = array(
+            'variables_ifvar'    => $this->__('PLG_ORDERNUMBER_REPL_IFVAR'),
+            'variables_ifop'     => '',
+            'variables_ifval'    => $this->__('PLG_ORDERNUMBER_REPL_IFVAL'),
+            'variables_then'     => $this->__(''),
+            'variables_thenvar'  => $this->__('PLG_ORDERNUMBER_REPL_SETVAR'),
+            'variables_thenval'  => $this->__('PLG_ORDERNUMBER_REPL_TOVAL'),
+            'sort'     => '',
+            'variables_settings' => '',
+        );
+        $html[] = '	<thead>';
+        $html[] = '		<tr class="ordernumber_variables_header">';
+        foreach ( $columns as $key => $column ) {
+        	$html[] = '<th class="' . $key . '">' . htmlspecialchars( $column ) . '</th>';
+        }
+        $html[] = '		</tr>';
+        $html[] = '		<tr id="ordernumber-replacements-empty-row" class="oton-empty-row-notice ' . (empty($variables)?"":"rowhidden") . '">';
+        $html[] = '			<td class="oton-empty-row-notice" colspan="8">';
+        $html[] = '				<em>' . $this->__('PLG_ORDERNUMBER_REPL_NOCUSTOMVARS') . '</em>';
+        $html[] = '				<input type="hidden" name="' . $name . '" value="" ' . (empty($variables))?'':'disabled' . '>';
+        $html[] = '			</td>';
+        $html[] = '		</tr>';
+        $html[] = '	</thead>';
+        $html[] = '	<colgroup>';
+        foreach ($columns as $key => $column) {
+        	$html[] = '<col class="' . $key . '" />';
+        }
+        $html[] = '	</colgroup>';
+        $html[] = '';
+        $html[] = '	<tbody>';
+        foreach ($variables as $var) {
+        	$html[] = $this->custom_variables_create_row($name, $var);
+        }
+        $html[] = '	</tbody>';
+        $html[] = '	<tfoot>';
+        $html[] = '		<tr class="addreplacement_row">';
+        $html[] = '			<td colspan=8 class="variable_add">';
+        $html[] = '				<div class="ordernumber-variables-addbtn ordernumber-btn" onClick="ordernumberVariablesAddRow(\'ordernumber_variables_template\', \'ordernumber_variables\')">';
+        $html[] = '					<div class="ordernumber-ajax-loading"><img src="' . $this->urlPath('images', 'icon-16-new.png' ) . '" class="ordernumber-counter-addbtn" /></div>';
+        $html[] = $this->__('PLG_ORDERNUMBER_REPL_ADDVAR');
+        $html[] = '				</div>';
+        $html[] = '			</td>';
+        $html[] = '		</tr>';
+        $html[] = '	</tfoot>';
+        $html[] = '</table>';
+        return implode("\n", $html);
+    }
+    
+    public function custom_variables_create_row($name, $values = array(), $disabled = '') {
+        $operator = (isset($values['conditionop'])?$values['conditionop']:'');
+        $operators = array(
+            'nocondition'  => $this->__('PLG_ORDERNUMBER_REPL_OP_NOCOND'),
+            'equals'       => '=', 
+            'contains'     => $this->__('PLG_ORDERNUMBER_REPL_OP_CONTAINS'), 
+            'smaller'      => '<',
+            'smallerequal' => '<=',
+            'larger'       => '>',
+            'largerequal'  => '>=', 
+            'startswith'   => $this->__('PLG_ORDERNUMBER_REPL_OP_STARTS'),
+            'endswith'     => $this->__('PLG_ORDERNUMBER_REPL_OP_ENDS'),
+        );
+        $html  = '
+        <tr>
+        	<td class="variables_ifvar"><input name="' . $name . '[conditionvar][]" value="' . (isset($values['conditionvar'])?htmlentities($values['conditionvar']):'') . '" ' . htmlentities($disabled) . '/></td>
+        	<td class="variables_ifop"      ><select name="' . $name . '[conditionop][]" ' . htmlentities($disabled) . ' style="width: 100px">';
+        foreach ($operators as $op => $opname) {
+        	$html .= '		<option value="' . $op . '" ' . (($op === $operator)?'selected':'') . '>' . htmlspecialchars($opname) . '</option>';
+        }
+        $html .= '</select></td>
+        	<td class="variables_ifval"   ><input name="' . $name . '[conditionval][]" value="' . (isset($values['conditionval'])?$values['conditionval']:'') . '" ' . htmlentities($disabled) . '/></td>
+        	<td class="variables_then">=></td>
+        	<td class="variables_thenvar"><input name="' . $name . '[newvar][]"       value="' . (isset($values['newvar'])?$values['newvar']:'') .       '" ' . htmlentities($disabled) . '/></td>
+        	<td class="variables_thenval"><input name="' . $name . '[newval][]"       value="' . (isset($values['newval'])?$values['newval']:'') .       '" ' . htmlentities($disabled) . '/></td>
+        	<td class="sort"></td>
+        	<td class="variables_settings"><img src="' . $this->urlPath('images', 'icon-16-delete.png' ) . '" class="ordernumber-replacement-deletebtn ordernumber-btn"></td>
+        </tr>';
+        return $html;
+    }
+
+    /**
+     * Modify the json that contains JavaScript setup code to be used by ordernumber.js
+     */
+	function addCustomJS(&$json) {}
+	function appendJS() {}
+	function createJSSetup() {
+		static $done = 0; // <= prevent double js code
+		$json = array();
+		$json['ajax_url'] = $this->ajax_url;
+		
+		foreach ($this->jstranslations as $key) {
+			$json[$key] = $this->__($key);
+		}
+		$this->addCustomJS($json);
+		$js='/* <![CDATA[ */
+var ajax_ordernumber = ' . json_encode($json) . ';
+';
+		$js .= $this->appendJS();
+		$js .= '/* ]]> */
+';
+		$done = 1;
+		return $js;
+	}
+	
+}
diff --git a/lib/OpenTools/Ordernumber/ordernumber_helper_magento.php b/lib/OpenTools/Ordernumber/ordernumber_helper_magento.php
new file mode 100644
index 0000000..6803e29
--- /dev/null
+++ b/lib/OpenTools/Ordernumber/ordernumber_helper_magento.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Advanced Ordernumbers magento-specific helper class
+ * Reinhold Kainhofer, Open Tools, office@open-tools.net
+ * @copyright (C) 2012-2015 - Reinhold Kainhofer
+ * @license AFL
+**/
+
+if (!class_exists( 'OrdernumberHelper' )) 
+	require_once (dirname(__FILE__) . '/library/ordernumber_helper.php');
+
+class OrdernumberHelperMagento extends OrdernumberHelper {
+	protected $maghelper = null;
+
+	function __construct($helper) {
+		parent::__construct();
+		$this->maghelper = $helper;
+		// TODO: Load translations
+// 		load_plugin_textdomain('opentools-ordernumbers', false, basename( dirname( __FILE__ ) ) . '/languages' );
+		// Magento-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 OrdernumberHelperMagento();
+		}
+		return $helper;
+    }
+	
+	/**
+	 * HELPER FUNCTIONS, Magento-specific
+	 */
+	public function __($string) {
+		$string = $this->readableString($string);
+		return $this->maghelper->__($string);
+	}
+	function urlPath($type, $file) {
+		// TODO
+// 		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');
+// 				}
+// 				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);
+	}
+
+
+}
-- 
GitLab