From e024d9dd920be6e6a0d4b32e484e5954409450a7 Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Mon, 1 Dec 2014 02:50:19 +0100
Subject: [PATCH] Implement counter editing in the plugin config; Some minor
 issues are left, the functionality is fully implemented

---
 fields/vmordernumbercounters.php              | 101 +++++++-----
 .../en-GB/en-GB.plg_vmshopper_ordernumber.ini |   4 +-
 .../en-GB.plg_vmshopper_ordernumber.sys.ini   |   4 +-
 ordernumber.php                               | 155 ++++++++++++++----
 ordernumber/assets/css/ordernumber.css        |  18 ++
 ordernumber/assets/images/icon-16-delete.png  | Bin 0 -> 555 bytes
 ordernumber/assets/images/icon-16-edit.png    | Bin 0 -> 623 bytes
 ordernumber/assets/images/icon-16-new.png     | Bin 0 -> 430 bytes
 ordernumber/assets/js/ordernumber.js          | 108 ++++++++++++
 9 files changed, 315 insertions(+), 75 deletions(-)
 create mode 100644 ordernumber/assets/css/ordernumber.css
 create mode 100644 ordernumber/assets/images/icon-16-delete.png
 create mode 100644 ordernumber/assets/images/icon-16-edit.png
 create mode 100644 ordernumber/assets/images/icon-16-new.png
 create mode 100644 ordernumber/assets/js/ordernumber.js

diff --git a/fields/vmordernumbercounters.php b/fields/vmordernumbercounters.php
index bf1a24d..4897222 100644
--- a/fields/vmordernumbercounters.php
+++ b/fields/vmordernumbercounters.php
@@ -2,7 +2,7 @@
 defined('_JEXEC') or die();
 /**
  *
- * @package	VirtueMart
+ * @package    VirtueMart
  * @subpackage Plugins  - Fields
  * @author Reinhold Kainhofer, Open Tools
  * @link http://www.open-tools.net
@@ -15,53 +15,62 @@ defined('_JEXEC') or die();
  */
  
 defined('DS') or define('DS', DIRECTORY_SEPARATOR);
+if (!class_exists( 'VmConfig' )) 
+    require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php');
+VmConfig::loadConfig();
 
 class JFormFieldVmOrdernumberCounters extends JFormField {
     var $_name = 'vmOrdernumberCounters';
     
     protected $countertype;
 
-	public function __get($name)
-	{
-		switch ($name)
-		{
-			case 'countertype':
-				return $this->$name;
-		}
+    public function __get($name)
+    {
+        switch ($name)
+        {
+            case 'countertype':
+                return $this->$name;
+        }
 
-		return parent::__get($name);
-	}
+        return parent::__get($name);
+    }
 
-	public function __set($name, $value)
-	{
-		switch ($name)
-		{
-			case 'countertype':
-				$this->$name = (string) $value;
-				break;
+    public function __set($name, $value)
+    {
+        switch ($name)
+        {
+            case 'countertype':
+                $this->$name = (string) $value;
+                break;
 
-			default:
-				parent::__set($name, $value);
-		}
-	}
+            default:
+                parent::__set($name, $value);
+        }
+    }
 
-	public function setup(SimpleXMLElement $element, $value, $group = null)
-	{
-		$return = parent::setup($element, $value, $group);
+    public function setup(SimpleXMLElement $element, $value, $group = null)
+    {
+        $return = parent::setup($element, $value, $group);
 
-		if ($return) {
-			$this->countertype  = (string) $this->element['countertype'];
-		}
+        if ($return) {
+            $this->countertype  = (string) $this->element['countertype'];
+        }
 
-		return $return;
-	}
-	
+        return $return;
+    }
+
+    protected function makeJSTranslationsAvailable() {
+        JText::script('PLG_ORDERNUMBER_COUNTER_QUERY_NAME');
+    }
     protected function getInput() {
+        $pluginpath = '/plugins/vmshopper/ordernumber/ordernumber/';
+        $doc = JFactory::getDocument()->addStyleSheet(JURI::root(true) . $pluginpath . 'assets/css/ordernumber.css');
+        $doc->addScript(JURI::root(true).$pluginpath . 'assets/js/ordernumber.js');
+        
         // Look up the current counters
         $db = JFactory::getDBO();
-        $db->setQuery('SELECT `number_format`, `count` FROM `#__virtuemart_shopper_plg_ordernumber` WHERE `number_type`='.(string)$this->countertype . ' ORDER BY `number_format`;' );
+        $db->setQuery('SELECT `number_format`, `count` FROM `#__virtuemart_shopper_plg_ordernumber` WHERE `number_type`='.$db->quote($this->countertype) . ' ORDER BY `number_format`;' );
         $counters = $db->loadObjectList();
-// JFactory::getApplication()->enqueueMessage("<pre>All counters: ".print_r($counters, 1)."</pre>", 'error');
         // Joomla 2.x uses <li> for the params and float:left on the controls, so we need to add that too
         $version = new JVersion();
         $float = "";
@@ -69,15 +78,29 @@ class JFormFieldVmOrdernumberCounters extends JFormField {
             $float = "float: left; ";
         }
         
-        $ret = "<table border=\"1\" style=\"border: 1px solid dark-gray; border-collapse: collapse; display: inline-table; $float\"><tr><th>".JText::_('PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER')."</th><th>".JText::_('PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE'). "</th></tr>";
-        $ret .= "<colgroup><col ><col style=\"text-align: center\" ></colgroup>";
+        $html=array();
+        $html[] = "<table class=\"vmordernumber-countertable table-striped \" display: inline-table; $float\">";
+        $html[] = "  <tr>";
+        $html[] = "    <th class='counter_format'>".JText::_('PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER')."</th>";
+        $html[] = "    <th class='counter_value'>".JText::_('PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE'). "</th>";
+        $html[] = "    <th class='counter_buttons'></th>";
+        $html[] = "  </tr>";
+        $html[] = "  <colgroup><col class='counter_type'><col style=\"text-align: center\" ><col ></colgroup>";
         foreach ($counters as $c) {
-            if ($c->number_format=="") {
-                $c->number_format = JText::_ ('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL');
+            $displayfmt = $c->number_format;
+            if ($displayfmt=="") {
+                $displayfmt = JText::_ ('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL');
             }
-            $ret .= "<tr><td>" . (string)$c->number_format . "</td><td>" . (string)$c->count . "</td></tr>";
+            $html[] = "  <tr class='counter_row counter_type_$this->countertype'>";
+            $html[] = "    <td class='counter_format'>" . (string)$displayfmt . "</td>";
+            $html[] = "    <td class='counter_value'>" . (string)$c->count . "</td>";
+            $html[] = "    <td class='counter_buttons'><img src='" .JURI::root(true).$pluginpath . "assets/images/icon-16-edit.png' class='vmordernumber-counter-editbtn vmordernumber-btn' onClick='ajaxEditCounter(this, $this->countertype, ".json_encode($c->number_format).", $c->count)' /><img src='" . JURI::root(true).$pluginpath . "assets/images/icon-16-delete.png' class='vmordernumber-counter-deletebtn vmordernumber-btn' onClick='ajaxDeleteCounter(this, $this->countertype, ".json_encode($c->number_format).", $c->count)' /></td>";
+            $html[] = "  </tr>";
         }
-        $ret .= "</table>";
-        return $ret;
+        $html[] = "  <tr class='addcounter_row'>";
+        $html[] = "    <td colspan=3 class='counter_add'><div class='vmordernumber-counter-addbtn vmordernumber-btn' onClick='ajaxAddCounter(this, $this->countertype)'><img src='" . JURI::root(true).$pluginpath . "assets/images/icon-16-new.png' class='vmordernumber-counter-addbtn' />" . JText::_('PLG_ORDERNUMBER_COUNTERLIST_ADD') . "</div></td>";
+        $html[] = "  </tr>";
+        $html[] = "</table>";
+        return implode("\n", $html);
     }
 }
\ No newline at end of file
diff --git a/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini b/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini
index fc4bdf7..37a3f73 100644
--- a/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini
+++ b/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini
@@ -48,4 +48,6 @@ PLG_ORDERNUMBER_CUSTOMERNR_PADDING_DESC="Select the minimum number of digits tha
 PLG_ORDERNUMBER_ORDERNR_ALLCOUNTERS="All counter values"
 PLG_ORDERNUMBER_COUNTERLIST_GLOBAL="<i>Global counter</i>"
 PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER="Counter format/name"
-PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE="Counter value"
\ No newline at end of file
+PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE="Counter value"
+PLG_ORDERNUMBER_COUNTERLIST_ADD="Add new counter"
+PLG_ORDERNUMBER_COUNTERLIST_EXISTS="Counter '%s' already exists."
diff --git a/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini b/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini
index fc4bdf7..37a3f73 100644
--- a/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini
+++ b/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini
@@ -48,4 +48,6 @@ PLG_ORDERNUMBER_CUSTOMERNR_PADDING_DESC="Select the minimum number of digits tha
 PLG_ORDERNUMBER_ORDERNR_ALLCOUNTERS="All counter values"
 PLG_ORDERNUMBER_COUNTERLIST_GLOBAL="<i>Global counter</i>"
 PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER="Counter format/name"
-PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE="Counter value"
\ No newline at end of file
+PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE="Counter value"
+PLG_ORDERNUMBER_COUNTERLIST_ADD="Add new counter"
+PLG_ORDERNUMBER_COUNTERLIST_EXISTS="Counter '%s' already exists."
diff --git a/ordernumber.php b/ordernumber.php
index 61b04eb..d422692 100644
--- a/ordernumber.php
+++ b/ordernumber.php
@@ -7,7 +7,11 @@
 **/
 
 defined('_JEXEC') or     die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' ) ;
-if (!class_exists('vmShopperPlugin')) require(JPATH_VM_PLUGINS . DS . 'vmshopperplugin.php');
+if (!class_exists('vmShopperPlugin')) 
+    require(JPATH_VM_PLUGINS . DS . 'vmshopperplugin.php');
+if (!class_exists( 'VmConfig' )) 
+    require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php');
+VmConfig::loadConfig();
 
 class plgVmShopperOrdernumber extends vmShopperPlugin {
 
@@ -34,6 +38,56 @@ class plgVmShopperOrdernumber extends vmShopperPlugin {
     // We don't need this function, but the parent class declares it abstract, so we need to overload
     function plgVmOnUpdateOrderBEShopper($_orderID) {}
     
+    function _getCounter($nrtype, $format) {
+        $db = JFactory::getDBO();
+        /* prevent sql injection attacks by escaping the user-entered format! Empty for global counter... */
+        /* For global counting, simply read the empty number_format entries! */
+        $q = 'SELECT `count` FROM `'.$this->_tablename.'` WHERE `number_type`='.(int)$nrtype.' AND `number_format`='.$db->quote($format);
+        $db->setQuery($q);
+        $existing = $db->loadResult();
+        $count = $existing?$existing:0;
+        return $count;
+    }
+    
+    function _counterExists($nrtype, $format) {
+        $db = JFactory::getDBO();
+        $q = 'SELECT `count` FROM `'.$this->_tablename.'` WHERE `number_type`='.(int)$nrtype.' AND `number_format`='.$db->quote($format);
+        $db->setQuery($q);
+        return ($db->loadResult() != null);
+    }
+    
+    // Insert new counter value into the db
+    function _addCounter($nrtype, $format, $value) {
+        $db = JFactory::getDBO();
+        $q = 'INSERT INTO `'.$this->_tablename.'` (`count`, `number_type`, `number_format`) VALUES ('.(int)$value.','.(int)$nrtype.', '.$db->quote($format).')';
+        $db->setQuery( $q );
+        $db->query();
+        return $db->getAffectedRows();
+    }
+
+    // Insert new counter value into the db or update existing one
+    function _setCounter($nrtype, $format, $value) {
+        $db = JFactory::getDBO();
+        $q = 'UPDATE `'.$this->_tablename.'` SET `count`= "'.(int)$value.'" WHERE `number_type`='.(int)$nrtype.' AND `number_format`='.$db->quote($format);
+        $db->setQuery( $q );
+        $db->query();
+        if ($db->getAffectedRows()<1) {
+            return $this->_addCounter($nrtype, $format, $value);
+        } else {
+            return $db->getAffectedRows();
+        }
+    }
+
+    // Insert new counter value into the db or update existing one
+    function _deleteCounter($nrtype, $format) {
+        $db = JFactory::getDBO();
+        $format = $db->escape ($format);
+        $q = 'DELETE FROM `'.$this->_tablename.'` WHERE `number_type`='.(int)$nrtype.' AND `number_format`='.$db->quote($format);
+        $db->setQuery( $q );
+        $db->query();
+        return $db->getAffectedRows();
+    }
+
     /* Return a random "string" of the given length taken from the given alphabet */
     static function randomString($alphabet, $len) {
         $alen = strlen($alphabet);
@@ -64,7 +118,6 @@ class plgVmShopperOrdernumber extends vmShopperPlugin {
     /* Extract the country information from the given ID */
     static function getCountryFromID ($country_id) {
         $db = JFactory::getDBO();
-    
         $query = 'SELECT * FROM `#__virtuemart_countries` WHERE `virtuemart_country_id` = ' . (int)$country_id;
         $db->setQuery($query);
         return $db->loadObject();
@@ -141,26 +194,12 @@ class plgVmShopperOrdernumber extends vmShopperPlugin {
         // If a separate counter format is given after the |, use it, otherwise reuse the number format itself as counter format
         $parts = explode ("|", $nr);
         $format = $parts[0];
-        $counterfmt = $parts[(count($parts)>1)?1:0];
-
+        
+        $counterfmt = ($global==1)?"":$parts[(count($parts)>1)?1:0];
+        
         // Look up the current counter
-        $db = JFactory::getDBO();
-        /* prevent sql injection attacks by escaping the user-entered format! Empty for global counter... */
-        /* For global counting, simply read the empty number_format entries! */
-        $counterfmt = $global?"":$db->getEscaped ($counterfmt);
-        $q1 = 'SELECT `count` FROM `'.$this->_tablename.'` WHERE `number_type`='.(int)$nrtype.' AND `number_format`="'.$counterfmt.'"';
-        $db->setQuery($q1);
-        $existing = $db->loadResult();
-        $count = $existing?($existing+1):1;
-
-        // Insert new counter value into the db
-        if ($existing) {
-            $q = 'UPDATE `'.$this->_tablename.'` SET `count`= "'.$count.'" WHERE `number_type`='.(int)$nrtype.' AND `number_format`="'.$counterfmt.'"';
-        } else {
-            $q = 'INSERT INTO `'.$this->_tablename.'` (`count`, `number_type`, `number_format`) VALUES ('.(int)$count.','.(int)$nrtype.', "'.$counterfmt.'")';
-        }
-        $db->setQuery( $q );
-        $db->query();
+        $count = $this->_getCounter($nrtype, $counterfmt) + 1;
+        $this->_setCounter($nrtype, $counterfmt, $count);
 
         // return the format with the counter inserted
         return str_replace ("#", sprintf('%0' . $padding . 's', $count), $format);
@@ -225,22 +264,70 @@ class plgVmShopperOrdernumber extends vmShopperPlugin {
     }
 
 
-	/**
-	 * plgVmOnSelfCallBE ... Called to execute some plugin action in the backend (e.g. set/reset dl counter, show statistics etc.)
-	 */
-/*	function plgVmOnSelfCallBE($type, $name, &$output) {
-		if ($name != $this->_name || $type != 'vmshopper') return false;
-		vmDebug('plgVmOnSelfCallBE');
-		
-		$db = JFactory::getDBO();
-		$nullDate = $db->getNullDate();
-	}*/
+    /**
+     * plgVmOnSelfCallBE ... Called to execute some plugin action in the backend (e.g. set/reset dl counter, show statistics etc.)
+     */
+    function plgVmOnSelfCallBE($type, $name, &$output) {
+        if ($name != $this->_name || $type != 'vmshopper') return false;
+        vmDebug('plgVmOnSelfCallBE');
+        $user = JFactory::getUser();
+        $authorized = ($user->authorise('core.admin','com_virtuemart') or
+                       $user->authorise('core.manage','com_virtuemart') or 
+                       $user->authorise('vm.orders','com_virtuemart'));
+        $output = array();
+        $output['authorized'] = $authorized;
+        if (!$authorized) return FALSE;
 
+        $action = vRequest::getCmd('action');
+        $counter= vRequest::getString('counter');
+        $nrtype = vRequest::getInt('nrtype');
+        $output['action'] = $action;
+        $output['success'] = 0; // default: unsuccessfull
+        switch ($action) {
+            case "deleteCounter":
+                $output['success'] = $this->_deleteCounter($nrtype, $counter);
+                break;
+            case "addCounter":
+                $value = vRequest::getInt('value',0);
+                if ($this->_counterExists($nrtype, $counter)) {
+                    $output['error'] = JText::sprintf('PLG_ORDERNUMBER_COUNTERLIST_EXISTS', $counter);
+                    $output['success'] = false;
+                } else {
+                    $output['success'] = $this->_addCounter($nrtype, $counter, $value);
+                    // Return the table row for the new counter in the JSON:
+                    $pluginpath = '/plugins/vmshopper/ordernumber/ordernumber/';
+                    $displayfmt = ($counter=="") ? JText::_('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL') : $counter;
+                    $html=array();
+                    $html[] = "<tr class='counter_row counter_type_$nrtype'>";
+                    $html[] = "  <td class='counter_format'>" . (string)$displayfmt . "</td>";
+                    $html[] = "  <td class='counter_value'>" . (string)$value . "</td>";
+                    $html[] = "  <td class='counter_buttons'><img src='" .JURI::root(true).$pluginpath . "assets/images/icon-16-edit.png' class='vmordernumber-counter-editbtn vmordernumber-btn' onClick='ajaxEditCounter(this, $nrtype, ".json_encode($counter).", $value)' /><img src='" . JURI::root(true).$pluginpath . "assets/images/icon-16-delete.png' class='vmordernumber-counter-deletebtn vmordernumber-btn' onClick='ajaxDeleteCounter(this, $nrtype, ".json_encode($counter).", $value)' /></td>";
+                    $html[] = "</tr>";
+                    $output['newrow'] = implode("\n", $html);
+                }
+                break;
+            case "setCounter":
+                $value = vRequest::getInt('value');
+                $output['success'] = $this->_setCounter($nrtype, $counter, $value);
+                break;
+        }
+        
+        // Also return all messages (in HTML format!):
+        // Since we are in a JSON document, we have to temporarily switch the type to HTML
+        // to make sure the html renderer is actually used
+        $document = JFactory::getDocument ();
+        $previoustype = $document->getType();
+        $document->setType('html');
+        $msgrenderer = $document->loadRenderer('message');
+        $output['messages'] = $msgrenderer->render('Message');
+        $document->setType($previoustype);
+    }
+    
     
     /* In versions before VM 2.6.8, the onStoreInstallPluginTable function was protected, so the installer couldn't call it to create the plugin table...
        This function simply is a public wrapper to make this function available to the installer on all VM versions: */
-	public function plgVmOnStoreInstallPluginTable($psType, $name='') {
-		return $this->onStoreInstallPluginTable($psType, $name);
-	}
+    public function plgVmOnStoreInstallPluginTable($psType, $name='') {
+        return $this->onStoreInstallPluginTable($psType, $name);
+    }
 
 }
diff --git a/ordernumber/assets/css/ordernumber.css b/ordernumber/assets/css/ordernumber.css
new file mode 100644
index 0000000..ca33790
--- /dev/null
+++ b/ordernumber/assets/css/ordernumber.css
@@ -0,0 +1,18 @@
+td.counter_value {
+    text-align: center;
+}
+
+table.vmordernumber-countertable {
+    border: 1px solid #888888;
+}
+
+table.vmordernumber-countertable.table-striped tbody > tr:nth-child(odd) > th {
+    background: #E0E0E0;
+}
+.vmordernumber-btn {
+    cursor: pointer;
+}
+
+col.counter_type, th.counter_type, td.counter_type {
+    display:none;
+}
\ No newline at end of file
diff --git a/ordernumber/assets/images/icon-16-delete.png b/ordernumber/assets/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/ordernumber/assets/images/icon-16-edit.png b/ordernumber/assets/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/ordernumber/assets/images/icon-16-new.png b/ordernumber/assets/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/ordernumber/assets/js/ordernumber.js b/ordernumber/assets/js/ordernumber.js
new file mode 100644
index 0000000..bee01ca
--- /dev/null
+++ b/ordernumber/assets/js/ordernumber.js
@@ -0,0 +1,108 @@
+var updateMessages = function(messages, area) {
+    jQuery( "#system-message-container #system-message div."+area+"-message").remove();
+    // Extract the messages from the returned string, add the ordernumber-message class (so the next ajax call
+    // can remove them again) and then move the messages to the original message container.
+    // Things are complicated by the fact that no #system-message element exists if no messages were printed so far
+    var newmessages = jQuery( messages ).find("div.alert").addClass(area+"-message");
+    if (!jQuery( "#system-message-container #system-message").length && newmessages.length) {
+        jQuery( "#system-message-container" ).append( "<div id='system-message'></div>" );
+    }
+    newmessages.appendTo( "#system-message-container #system-message");
+}
+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("You are not authorized to modify order number counters.");
+    } 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 (msgprefix+"Please enter the new value for the counter '" + counter.counter + "' (current value: " + counter.value + "):", counter.value);
+        if (value != null)
+            value = parseInt(value);
+        if (isNaN(value)) 
+            msgprefix = "You entered an invalid value for the counter.\n\n";
+    }
+    if (value != null) {
+        jQuery.ajax({
+            type: "POST",
+            cache: false,
+            dataType: "text", // Read text, but interpret as JSON later in the done method (prevents a warning!)
+            url: "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&action=setCounter&format=json",
+            data: { nrtype: counter.type, counter: counter.counter, value: value },
+            success: function( data ) {
+                var json = data ? jQuery.parseJSON(data) : null;
+                handleJSONResponse(json, counter);
+                if (json.success>0) {
+                    jQuery(counter.row).children(".counter_value").text(value);
+                } else {
+                    alert ("Failed modifying counter "+counter.counter);
+                }
+            },
+            error: function() { alert ("ERROR: Failed modifying counter "+counter.counter); }
+        });
+    }
+}
+var ajaxDeleteCounter = function (btn, nrtype, ctr, value) {
+    var counter = getCounterData(btn);
+    counter.type=nrtype;
+    counter.counter=ctr;
+    counter.value=value;
+    var proceed = confirm ("Really delete counter '"+counter.counter+"' with value '"+counter.value+"'?");
+    if (proceed == true) {
+        jQuery.ajax({
+            type: "POST",
+            cache: false,
+            dataType: "text", // Read text, but interpret as JSON later in the done method (prevents a warning!)
+            url: "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&action=deleteCounter&format=json",
+            data: { nrtype: counter.type, counter: counter.counter },
+            success: function( data ) {
+                var json = data ? jQuery.parseJSON(data) : null;
+                handleJSONResponse(json, counter);
+                if (json.success>0) {
+                    jQuery(counter.row).fadeOut(1500, function() { $(this).remove(); });
+                } else {
+                    alert ("Failed modifying counter "+counter.counter);
+                }
+            },
+            error: function() { alert ("ERROR: Failed modifying counter "+counter.counter); }
+        });
+    }
+}
+var ajaxAddCounter = function (btn, nrtype) {
+    var row = jQuery(btn).parents("tr.addcounter_row");
+    var countername = prompt ("Please enter the format/name of the new counter:");
+    if (countername != null) {
+        jQuery.ajax({
+            type: "POST",
+            cache: false,
+            dataType: "text", // Read text, but interpret as JSON later in the done method (prevents a warning!)
+            url: "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&action=addCounter&format=json",
+            data: { nrtype: nrtype, counter: countername },
+            success: function( data ) {
+                var json = data ? jQuery.parseJSON(data) : null;
+                handleJSONResponse(json, { type: nrtype, counter: countername, value: 0, row: row });
+                if (json.success>0) {
+                    if (json.newrow) {
+                        jQuery(row).before(jQuery(json.newrow));
+                    }
+                }
+            },
+            error: function() { alert ("ERROR: Failed adding counter "+countername); }
+        });
+    }
+}
-- 
GitLab