From 22227d012844f1603687fa8ef837157f2e6598eb Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Fri, 7 Nov 2014 18:09:41 +0100
Subject: [PATCH] V1.4: Fix changing VM shoppergroups for good (need to use
 VmTable rather than the model, and reset the cache...)

---
 Makefile                                      |   2 +-
 buyer_assign_group.php                        |  79 +++++++++++++-----
 buyer_assign_group.xml                        |   2 +-
 ..._opentools_vm2_buyer_assign_group_v1.4.zip | Bin 0 -> 9543 bytes
 4 files changed, 62 insertions(+), 21 deletions(-)
 create mode 100644 releases/plg_opentools_vm2_buyer_assign_group_v1.4.zip

diff --git a/Makefile b/Makefile
index e2a6910..df3d015 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 BASE=buyer_assign_group
 PLUGINTYPE=vmcustom
 ZIPBASE=opentools_vm2
-VERSION=1.3
+VERSION=1.4
 
 PLUGINFILES=$(BASE).php $(BASE).script.php $(BASE).xml index.html
 
diff --git a/buyer_assign_group.php b/buyer_assign_group.php
index 2fd5456..6a75389 100644
--- a/buyer_assign_group.php
+++ b/buyer_assign_group.php
@@ -30,7 +30,6 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 		} else {
 			$this->setConfigParameterable ('customfield_params', $varsToPush);
 		}
-// 		$this->onStoreInstallPluginTable($this->_psType);
 	}
 
 	/**
@@ -46,7 +45,6 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 		} else {
 			$paramName = 'customfield_params';
 		}
-		
 		$html .= '<table class="admintable">';
 		$html .= VmHTML::row (array('JHTML', '_'),'VMCUSTOM_BUYER_GROUP_JOOMLA', 'access.usergroup', $paramName.'['.$row.'][joomla_groups][]', $field->joomla_groups, ' multiple data-placeholder=" "', false);
 		$html .= VmHTML::row (array('JHTML', '_'),'VMCUSTOM_BUYER_GROUP_JOOMLA_REMOVE', 'access.usergroup', $paramName.'['.$row.'][joomla_groups_remove][]', $field->joomla_groups_remove, ' multiple data-placeholder=" "', true);
@@ -111,10 +109,49 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 		return $SQLfields;
 	}
 	
+	/* This function does NOT load the whole user, it just loads enough to have the Joomla
+	   groups and the VM shopper groups, i.e. it loads all data from the vmusers and the
+	   vmuser_shoppergroups table, and the Joomla user information, but nothing else */
+	function loadUserGroupData($uid) {
+		if (empty($uid)) return null;
+
+		$db = JFactory::getDBO();
+
+		$userModel = VmModel::getModel('user');
+		$user = $userModel->getTable('vmusers');
+		$user->load((int)$uid);
+		$user->JUser = JUser::getInstance($uid);
+
+		// Add the virtuemart_shoppergroup_ids
+		$xrefTable = $userModel->getTable('vmuser_shoppergroups');
+		$user->shopper_groups = $xrefTable->load($uid);
+		if(empty($user->shopper_groups)) $user->shopper_groups = array();
+
+		$site = JFactory::getApplication ()->isSite ();
+		if ($site) {
+			$shoppergroupmodel = VmModel::getModel('ShopperGroup');
+			$shoppergroupmodel->appendShopperGroups($user->shopper_groups,$user->JUser,$site);
+		}
+		$user->shopper_groups = (array)$user->shopper_groups;
+
+		return $user;
+	}
+	
+	/** This functions makes sure the user model clears the cache of the given user, because the 
+	    user data was modified directly in the database. In VM2 there is only the last user 
+	    cached, so make sure to change the user id by first setting it to 0 and then to the real 
+	    uid. Otherwise the cache would not be erased if the uid was the last requested. */
+	function clearUserCache($uid) {
+		$userModel = VmModel::getModel('user');
+		$userModel->_data = null;
+		$userModel->setId(0);   // <- Make sure the cache is really, really erased in VM2!
+		$userModel->setId($uid);
+	}
+	
 	function setShopperGroups($uid, $groups) {
+		$this->clearUserCache($uid);
 		$noError = true;
 		$userModel = VmModel::getModel('user');
-		$userModel->setId($uid);
 		$shoppergroupmodel = VmModel::getModel('ShopperGroup');
 		$defaultgroup = $shoppergroupmodel->getDefault(0);
 
@@ -133,6 +170,7 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 			vmError('Set shoppergroup '.$error);
 			$noError = false;
 		}
+		$user_shoppergroups_table->emptyCache();
 		return $noError;
 	}
 	
@@ -181,9 +219,7 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 		foreach ($orderEntries as $e) {
 			$uid = $e['virtuemart_user_id'];
 			if (!isset($users[$uid])) {
-				$userModel->setId($uid);
-				$users[$uid] = $userModel->getUser();
-				$users[$uid]->shopper_groups = (array)$users[$uid]->shopper_groups;
+				$users[$uid] = $this->loadUserGroupData($uid);
 			}
 			$cid = $e['virtuemart_custom_id'];
 			if (!isset($customs[$cid])) {
@@ -203,8 +239,8 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 				$purchased   =  in_array($order_status, $pstates[$cid]) && !in_array($old_order_status, $pstates[$cid]);
 				$unpurchased = !in_array($order_status, $pstates[$cid]) &&  in_array($old_order_status, $pstates[$cid]);
 
+				$modified = false;
 				if ($purchased) {
-					$modified = false;
 					if ($e['group_type']==0) { // Joomla User Group
 						if ($e['group_add']==1 && !in_array($e['group_id'], $users[$uid]->JUser->groups)) { // Add to Joomla user group
 							$modified = JUserHelper::addUserToGroup ($uid, $e['group_id']);
@@ -220,13 +256,10 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 					}
 					if ($modified) {
 						$this->setModifiedFlag ($e, $modified);
+						// clear the user model cache and update update the $users array so the next step in the loop has the correct groups if the user is added to another group
+						$this->clearUserCache($uid);
+						$users[$uid] = $this->loadUserGroupData($uid);
 					}
-					// Update the $users array so the next step in the loop has the correct groups if the user is added to another group
-					$userModel->_data = null;
-					$userModel->setId(0); // <- This makes sure to invalidate the cache
-					$userModel->setId($uid);
-					$users[$uid] = $userModel->getUser();
-					$users[$uid]->shopper_groups = (array)$users[$uid]->shopper_groups;
 				} elseif ($unpurchased && $e['modified']) {
 					// Undo the addition/removal when a product purchase is cancelled
 					if ($e['group_type']==0) { // Joomla User Group
@@ -246,11 +279,8 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 					$this->setModifiedFlag ($e, 0);
 				}
 				// Reload the user data, because shopper groups are NOT automatically updated in the data structure in memory!
-				$userModel->_data = null;
-				$userModel->setId(0); // <- This makes sure to invalidate the cache
-				$userModel->setId($uid);
-				$users[$uid] = $userModel->getUser();
-				$users[$uid]->shopper_groups = (array)$users[$uid]->shopper_groups;
+				$this->clearUserCache($uid);
+				$users[$uid] = $this->loadUserGroupData($uid);
 			}
 			catch (Exception $ex) {
 				JFactory::getApplication()->enqueueMessage("ERROR:  <pre>".$ex->getMessage()."</pre>", 'info');
@@ -261,7 +291,7 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 	
 	// VM2.x compat:
 	function plgVmOnUpdateOrder($data, $old_order_status) {
-		return $this->plgVmOnUpdateOrderShipment($data, $old_order_status);
+		return $this->updateOrderStatus($data->virtuemart_order_id, $data->order_status, $old_order_status);
 	}
 	// VM3.x
 	function plgVmOnUpdateOrderShipment($data, $old_order_status) {
@@ -325,6 +355,17 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin {
 			$this->updateOrderStatus($order_id, $order['details']['BT']->order_status, '');
 		}
 	}
+
+// 	function plgVmOnSelfCallBE($type, $name, &$output) {
+// 		if ($name != $this->_name || $type != 'vmcustom') return false;
+// 		vmDebug('plgVmOnSelfCallBE');
+// 		
+// 		$db = JFactory::getDBO();
+// 		$db->setQuery("SELECT * FROM `".$this->_tablename.";");
+// 		$val = $db->loadAssocList();
+// 		
+// 		JFactory::getApplication()->enqueueMessage("<pre>plgVmOnSelfCallBE, type=$type, name=$name, full database contents:".print_r($val,1)."</pre>", 'error');		
+// 	}
 }
 
 // No closing tag
\ No newline at end of file
diff --git a/buyer_assign_group.xml b/buyer_assign_group.xml
index c3f0b0d..6a58807 100644
--- a/buyer_assign_group.xml
+++ b/buyer_assign_group.xml
@@ -6,7 +6,7 @@
     <authorUrl>http://www.open-tools.net/</authorUrl>
     <copyright>Copyright (C) 2013-2014 Reinhold Kainhofer. All rights reserved.</copyright>
     <license>http://www.gnu.org/licenses/gpl.html GNU/GPL v3+</license>
-    <version>1.3</version>
+    <version>1.4</version>
     <description>VMCUSTOM_BUYER_GROUP_DESC</description>
     <files>
         <filename plugin="buyer_assign_group">buyer_assign_group.php</filename>
diff --git a/releases/plg_opentools_vm2_buyer_assign_group_v1.4.zip b/releases/plg_opentools_vm2_buyer_assign_group_v1.4.zip
new file mode 100644
index 0000000000000000000000000000000000000000..946926df1e6be9bfb72f3b581ef465dedb88315d
GIT binary patch
literal 9543
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

literal 0
HcmV?d00001

-- 
GitLab