From 43928984b1cc3c5603c3ef072b31506518490b8d Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer <reinhold@kainhofer.com> Date: Sun, 18 Aug 2013 00:09:43 +0200 Subject: [PATCH] Version 0.1: Adding/removing to/from Joomla/VM groups finally works --- buyer_assign_group.php | 161 ++++++++++-------- ..._opentools_vm2_buyer_assign_group_v0.1.zip | Bin 0 -> 7308 bytes 2 files changed, 86 insertions(+), 75 deletions(-) create mode 100644 releases/plg_opentools_vm2_buyer_assign_group_v0.1.zip diff --git a/buyer_assign_group.php b/buyer_assign_group.php index 2c09322..6bdf051 100644 --- a/buyer_assign_group.php +++ b/buyer_assign_group.php @@ -13,7 +13,7 @@ defined('_JEXEC') or die( 'Direct Access to ' . basename( __FILE__ ) . ' is not if (!class_exists('vmCustomPlugin')) require(JPATH_VM_PLUGINS . DS . 'vmcustomplugin.php'); class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin { - + var $counter=0; function __construct(& $subject, $config) { parent::__construct($subject, $config); $this->_tablepkey = 'id'; @@ -38,8 +38,6 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin { $html = ''; $this->parseCustomParams($field); -// $html .= "<pre>States: ".join(", ", $this->purchased_status)."</pre>"; - $html .= "<pre>Field: ".print_r($this, 1)."</pre>"; $html .= '<table class="admintable">'; $html .= VmHTML::row (array('JHTML', '_'),'VMCUSTOM_BUYER_GROUP_JOOMLA', 'access.usergroup', 'custom_param['.$row.'][joomla_groups][]', $field->joomla_groups, ' multiple data-placeholder=" "', false); $html .= VmHTML::row (array('JHTML', '_'),'VMCUSTOM_BUYER_GROUP_JOOMLA_REMOVE', 'access.usergroup', 'custom_param['.$row.'][joomla_groups_remove][]', $field->joomla_groups_remove, ' multiple data-placeholder=" "', true); @@ -97,22 +95,53 @@ class plgVmCustomBuyer_Assign_Group extends vmCustomPlugin { return $SQLfields; } + function setShopperGroups($uid, $groups) { + $noError = true; + $userModel = VmModel::getModel('user'); + $userModel->setId($uid); + $shoppergroupmodel = VmModel::getModel('ShopperGroup'); + $defaultgroup = $shoppergroupmodel->getDefault(0); + + if(empty($groups) or ($groups == array($defaultgroup->virtuemart_shoppergroup_id))) { + $groups = array(); + } + + // Bind the form fields to the table + $shoppergroupData = array('virtuemart_user_id'=>$uid, + 'virtuemart_shoppergroup_id'=>$groups); + $user_shoppergroups_table = $userModel->getTable('vmuser_shoppergroups'); + $shoppergroupData = $user_shoppergroups_table -> bindChecknStore($shoppergroupData); + $errors = $user_shoppergroups_table->getErrors(); + foreach($errors as $error){ + $this->setError($error); + vmError('Set shoppergroup '.$error); + $noError = false; + } + return $noError; + } + function addShopperGroup($user, $group) { - # TODO + $groups = $user->shopper_groups; + if (!in_array($group, $groups)) { + $groups[] = $group; + return $this->setShopperGroups($user->virtuemart_user_id, $groups); + } + return false; } function removeShopperGroup($user, $group) { - # TODO + $groups = $user->shopper_groups; + if (in_array($group, $groups)) { + $groups=array_diff($groups, array($group)); + return $this->setShopperGroups($user->virtuemart_user_id, $groups); + } + return false; } function setModifiedFlag ($entry, $value) { -JFactory::getApplication()->enqueueMessage("setModifiedFlag: entry=<pre>".print_r($entry,1)."</pre>", 'error'); - $db = JFactory::getDbo(); - $db->setQuery("UPDATE `".$this->_tablename."` SET `modified`=".(int)$value." WHERE `id`=".$entry['id']); - if (!$db->query()) { - JFactory::getApplication()->enqueueMessage("SQL query FAILED: Message: ".$db->getErrorMsg().", SQL: <pre>".$db->getQuery()."</pre>", 'error'); - } - $this->updateOrderStatus($order_id, $order['details']['BT']->order_status, ''); - - # TODO + $db = JFactory::getDbo(); + $db->setQuery("UPDATE `".$this->_tablename."` SET `modified`=".(int)$value." WHERE `id`=".$entry['id']); + if (!$db->query()) { + JFactory::getApplication()->enqueueMessage("SQL query FAILED: Message: ".$db->getErrorMsg().", SQL: <pre>".$db->getQuery()."</pre>", 'error'); + } } function updateOrderStatus ($order_id, $order_status, $old_order_status) { @@ -148,78 +177,58 @@ JFactory::getApplication()->enqueueMessage("setModifiedFlag: entry=<pre>".print_ $pstates[$cid] = $c->purchased_status; } } -foreach ($users as $u) { -JFactory::getApplication()->enqueueMessage("User: Joomla groups <pre>".print_r($u->JUser->groups,1)."</pre>, Shopper Groups: <pre>".print_r($u->shopper_groups,1)."</pre>", 'info'); -} -// JFactory::getApplication()->enqueueMessage("User: <pre>".print_r($users,1)."</pre>", 'info'); -// JFactory::getApplication()->enqueueMessage("User: <pre>".print_r($users,1)."</pre>", 'info'); // 3) Check which custom field entries need some change foreach ($orderEntries as $e) { -try { - $uid = $e['virtuemart_user_id']; - $cid = $e['virtuemart_custom_id']; - $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]); + try { + $uid = $e['virtuemart_user_id']; + $cid = $e['virtuemart_custom_id']; + $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]); -JFactory::getApplication()->enqueueMessage("Order status: $order_status, old order status: $old_order_status, pstates: ".print_r($pstates[$cid],1), 'info'); -JFactory::getApplication()->enqueueMessage("Purchased: $purchased, Unpurchased: $unpurchased", 'info'); - if ($purchased) { - $modified = false; - if ($e['group_type']==0) { // Joomla User Group -// $modified = ($e['group_add'] != ); - if ($e['group_add']==1 && !in_array($e['group_id'], $users[$uid]->JUser->groups)) { // Add to Joomla user group -JFactory::getApplication()->enqueueMessage("Trying to add user $uid to group ".$e['group_id'], 'info'); - $res = JUserHelper::addUserToGroup ($uid, $e['group_id']); - } elseif ($e['group_add']==0 && in_array($e['group_id'], $users[$uid]->JUser->groups)) { // Remove from Joomla user group -JFactory::getApplication()->enqueueMessage("Trying to remove user $uid from group ".$e['group_id'], 'info'); - $res = JUserHelper::removeUserFromGroup ($uid, $e['group_id']); - } - $modified = $res; -JFactory::getApplication()->enqueueMessage("Result: ".print_r($res,1), 'info'); - } elseif ($e['group_type']=1) { // Virtuemart Shopper Group - if ($e['group_add']==1) { // Add to Virtuemart Shopper group - $res = $this->addShopperGroup($users[$uid], $e['group_id']); - } elseif ($e['group_add']==0) { // Remove from Virtuemart Shopper group - $res = $this->removeShopperGroup ($users[$uid], $e['group_id']); + 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']); + } elseif ($e['group_add']==0 && in_array($e['group_id'], $users[$uid]->JUser->groups)) { // Remove from Joomla user group + $modified = JUserHelper::removeUserFromGroup ($uid, $e['group_id']); + } + } elseif ($e['group_type']=1) { // Virtuemart Shopper Group + if ($e['group_add']==1) { // Add to Virtuemart Shopper group + $modified = $this->addShopperGroup($users[$uid], $e['group_id']); + } elseif ($e['group_add']==0) { // Remove from Virtuemart Shopper group + $modified = $this->removeShopperGroup ($users[$uid], $e['group_id']); + } } - } - if ($modified) { - $this->setModifiedFlag ($e, $modified); - } - } elseif ($unpurchased && $e['modified']) { - // Undo the addition/removal when a product purchase is cancelled - if ($e['group_type']==0) { // Joomla User Group -JFactory::getApplication()->enqueueMessage("Trying to Undo add (".$e['group_add'].") user $uid to group ".$e['group_id'], 'info'); - if ($e['group_add']==1) { // Remove from Joomla user group again - $res = JUserHelper::removeUserFromGroup ($uid, $e['group_id']); - } elseif ($e['group_add']==0) { // Add to Joomla user group again - $res = JUserHelper::addUserToGroup ($uid, $e['group_id']); + if ($modified) { + $this->setModifiedFlag ($e, $modified); } -JFactory::getApplication()->enqueueMessage("Result: ".print_r($res,1), 'info'); - } elseif ($e['group_type']==1) { // Virtuemart Shopper Group - if ($e['group_add']==1) { // Remove from Virtuemart Shopper group again - $modified = $this->removeShopperGroup($users[$uid], $e['group_id']); - } elseif ($e['group_add']==0) { // Add from Virtuemart Shopper group again - $modified = $this->addShopperGroup ($users[$uid], $e['group_id']); + } elseif ($unpurchased && $e['modified']) { + // Undo the addition/removal when a product purchase is cancelled + if ($e['group_type']==0) { // Joomla User Group + if ($e['group_add']==1) { // Remove from Joomla user group again + $modified = JUserHelper::removeUserFromGroup ($uid, $e['group_id']); + } elseif ($e['group_add']==0) { // Add to Joomla user group again + $modified = JUserHelper::addUserToGroup ($uid, $e['group_id']); + } + } elseif ($e['group_type']==1) { // Virtuemart Shopper Group + if ($e['group_add']==1) { // Remove from Virtuemart Shopper group again + $modified = $this->removeShopperGroup($users[$uid], $e['group_id']); + } elseif ($e['group_add']==0) { // Add from Virtuemart Shopper group again + $modified = $this->addShopperGroup ($users[$uid], $e['group_id']); + } } + // Clear the modified flag in the database + $this->setModifiedFlag ($e, 0); } - // Clear the modified flag in the database - $this->setModifiedFlag ($e, 0); } -} -catch (Exception $ex) { -JFactory::getApplication()->enqueueMessage("ERROR: <pre>".$ex->getMessage()."</pre>", 'info'); - $ex->getMessage(); - JLog::add('Unable to add/remove user to/from group'); -} + catch (Exception $ex) { + JFactory::getApplication()->enqueueMessage("ERROR: <pre>".$ex->getMessage()."</pre>", 'info'); + JLog::add('Unable to add/remove user to/from group: '.$ex->getMessage()); + } } - - -// JFactory::getApplication()->enqueueMessage("Order Entries: <pre>".print_r($orderEntries,1)."</pre>", 'info'); -// JFactory::getApplication()->enqueueMessage("Purchased States: <pre>".print_r($pstates,1)."</pre>", 'info'); - } function plgVmCouponUpdateOrderStatus($data, $old_order_status) { @@ -238,6 +247,8 @@ JFactory::getApplication()->enqueueMessage("ERROR: <pre>".$ex->getMessage()."</ $uid = $user->JUser->id; $order_id = $order['details']['BT']->virtuemart_order_id; + $orderModel = VmModel::getModel('orders'); + $order = $orderModel->getOrder($order_id); $values = array(); $customModel = VmModel::getModel('customfields'); diff --git a/releases/plg_opentools_vm2_buyer_assign_group_v0.1.zip b/releases/plg_opentools_vm2_buyer_assign_group_v0.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..925051084c99798dec6134b7b811ead03676e994 GIT binary patch literal 7308 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 HOM-X+Y$>}? literal 0 HcmV?d00001 -- GitLab