News:

Support the VirtueMart project and become a member

Main Menu

Plugin: save multiple values

Started by sim085, June 26, 2013, 17:59:15 PM

Previous topic - Next topic

sim085

Hello,

I am developing a plugin for VirtueMart based on the "Specification" that comes out of the box with VirtueMart. I created my own table in the same this is done by this plugin. Instead of text fields I show a "select" component with attribute "multiple". This correctly allows me to select multiple items from the select field. However when I hit the save button only one of these values gets saved.

I was wondering does anyone know how I could change the code to allow all selected options to be saved. Here is my code:


function __construct(& $subject, $config) {

parent::__construct($subject, $config);

$this->_tablepkey = 'id';
$this->tableFields = array_keys($this->getTableSQLFields());
$this->varsToPush = array(
'contact_id'=> array('', 'string'),
);

$this->setConfigParameterable('custom_params',$this->varsToPush);
}

function getTableSQLFields() {
$SQLfields = array(
    'id' => 'int(11) unsigned NOT NULL AUTO_INCREMENT',
    'virtuemart_product_id' => 'int(11) UNSIGNED DEFAULT NULL',
    'virtuemart_custom_id' => 'int(11) UNSIGNED DEFAULT NULL',
    'contact_id' => 'varchar(1024) NOT NULL DEFAULT \'\''
);

return $SQLfields;
}

function plgVmOnStoreProduct($data,$plugin_param){
return $this->OnStoreProduct($data,$plugin_param);
}


PRO

OnDisplayProductBE   ?

how are you combining them?

& are you combining them?


sim085

#2
Quote from: PRO on June 26, 2013, 21:32:07 PM
OnDisplayProductBE   ? how are you combining them?

Hello, I am not overriding OnDisplayProductBE. I am overriding plgVmOnProductEdit. Here I build a select element as follows:


$html .= ' <select multiple name="plugin_param['.$row.']['.$this->_name.'][contact_id]">';
if(strrpos($this->params->contact_id, "1") === false):
$html .= ' <option value="1">A</option>';
else:
$html .= ' <option value="1" selected="selected">A</option>';
endif;
if(strrpos($this->params->contact_id, "2") === false):
$html .= ' <option value="2">B</option>';
else:
$html .= ' <option value="2" selected="selected">B</option>';
endif;
if(strrpos($this->params->contact_id, "3") === false):
$html .= ' <option value="3">C</option>';
else:
$html .= ' <option value="3" selected="selected">C</option>';
endif;
$html .= ' </select>';


The "multiple" attribute on the "select" element allows me to select mutliple elements. I do NOT know from where I can get these values and turn them for example in a comma separated string to save inside the database.

Quote from: PRO on June 26, 2013, 21:32:07 PM
are you combining them?

How and where would I do that? in plgVmOnStoreProduct?


sim085

Quote from: PRO on June 27, 2013, 01:46:00 AM
http://stackoverflow.com/questions/6797736/multiple-select-box-values-to-csv

Thank for that link. The one thing I cannot understand is where I have to do this transformation from array to string. I am going through the API (http://docs.virtuemart.net/api-vm2/d4/d4a/vmcustomplugin_8php_source.html) and also turned vm debug on to try and see what is going on, however I cannot figure out at what place (or how to override the function) that is responsible to persist the form data in the database, or another place where I can do the transformation before the form data is persisted in the database.

The variables inside plgVmOnStoreProduct do not seem to be related to the plugin data ... but I could be wrong of course.

PRO



this wont solve your problem, but this is my plugin, you can see how it separates a comma separated string. into a select list with Jhtml


   function plgVmOnDisplayProductVariantFE($field,&$idx,&$group) {
      // default return if it's not this plugin
       if ($field->custom_element != $this->_name) return '';
      $this->parseCustomParams($field);
      $options = explode(',', $field->custom_drop);
      $class='';
      $selects= array();
      if(!class_exists('CurrencyDisplay')) require(JPATH_VM_ADMINISTRATOR.DS.'helpers'.DS.'currencydisplay.php');
      $currency = CurrencyDisplay::getInstance();
      foreach ($options as $valuesWithPrice) {
         $valueWithPrice = explode('|', $valuesWithPrice);

         if ( isset ($valueWithPrice[1]) ) {
            $op = $valueWithPrice[1][0];
            $price = substr($valueWithPrice[1], 1) ;
            $text = $valueWithPrice[0].' ('.$op.$currency->priceDisplay((float)$price).')';
         } else {
            $text = $valueWithPrice[0] ;
         }
         $selects[] = array('value' =>$valueWithPrice[0], 'text' => $text );
      }
      $html = JHTML::_('select.genericlist', $selects,'customPlugin['.$field->virtuemart_customfield_id.']['.$this->_name.'][custom_drop]','','value','text',$selects[0],false,true);
      $group->display .= $html;
      return true;
    }



so, i think you should be able to do it with this example
You see how they add the
multiple="multiple"

in this thread
http://forum.joomla.org/viewtopic.php?p=2507188

JHTML::_('select.genericlist', $options,'supplier[]', 'class="inputbox"  multiple="multiple"','value','text',explode(',', $this->item->supplier));

PRO

WAIT:

you are not having a problem on the front end ? this is not a cart variant?

you just want to display some strings on the front end?

sim085

#7
Quote from: PRO on June 28, 2013, 03:09:50 AM
you just want to display some strings on the front end?

Yes, my aim is to link (out of the box) "Contacts" with Products. After going through VirtueMart I thought of using the Custom Fields (is this wrong?).
My aim is to - from the back end - link the Product to one or more Contact (i.e. - in the database I have a list of contact ids), and then in the front end I will simply display the contact name and email. 

From the front end the users will have no inputs.

At the moment I am stuck because I cannot identify in which place I am supposed to change the array (the selected values) into a comma separated string. 

Note: I also do not have a problem with to display a list on the BE (at the moment this is a static list will change that later). My problem is where to change the array of selected options to a comma separated string after an administrator clicks the save button in the backend.


PRO


sim085

My aim is to allow the back-end user to add more then one contact to every product. I am assuming most of the times it will be one, but it could be two or three sometimes; which is why I want to allow multi-select option.

PRO

Quote from: sim085 on June 28, 2013, 10:56:04 AM
My aim is to allow the back-end user to add more then one contact to every product. I am assuming most of the times it will be one, but it could be two or three sometimes; which is why I want to allow multi-select option.

you could easily just use regular "string" custom fields, with a little customization
http://forum.virtuemart.net/index.php?topic=99225.0
http://forum.virtuemart.net/index.php?topic=97419.0

Just set the default of the field

Anchor|link


<?php foreach ($this->product->customfieldsSorted[$this->position] as $field) {
         if ($field->layout_pos == my-position) {
$link = strstr($field->display,"|") ;
      $link=str_replace( '|', '', $link );
      $linkanchor=str_replace( $link, '', $links );
      $linkanchor=str_replace( '|', '', $linkanchor );
      ?>
      <li><a href="<?php echo $link ?>"><?php echo $linkanchor ?></a></li>
         }
       }
     <?php  ?>
      


sim085

#11
Quote from: PRO on June 28, 2013, 11:15:55 AM
you could easily just use regular "string" custom fields, with a little customization
http://forum.virtuemart.net/index.php?topic=99225.0
http://forum.virtuemart.net/index.php?topic=97419.0

That would mean I have to insert the contact name and email, etc.
The solution I am trying to develop is to link a product with an actual Joomla Contact, i.e. the plugin I am trying to develop would show all the contacts, the user select one or many. Then when generating the front end I would get the contact ids and from that I get the contacts information; name, email, photo, description, link to their page, etc.

This is why I went for a custom plugin.

There is no place where I can intercept what is going to be saved before this is actually saved?

sim085

Looking at the API  I would have thought I need to override

storePluginInternalData (&$values, $primaryKey=0, $id=0, $preload=FALSE)

However I do not know if my assumption is right, or how to actually override a function from my php code.

Here is the function API:
http://docs.virtuemart.net/api-vm2/de/d46/classvm_plugin.html#a4d80cfc9abab8160869f8da44228eca6


PRO

no you dont,

have you looked at the links I posted above? what have you tried?

sim085

Quote from: PRO on June 28, 2013, 19:41:37 PM
have you looked at the links I posted above? what have you tried?

Yes, I added the extra empty bracket in the name of the SELECT element to get multiple values (I confirmed this with vmdebug). I did see the links you send me, but my understanding is that using a "string" custom field would mean I have to stay insert "contact|email|etc". My target is to create a link between VirtueMart and Joomla contacts.

As I said I turned vmdebug on and I believe I found my problem. When I save vmdebug prints the following:


vmdebug OnStoreProduct return because key displaycontacts!== specification


This message is being printed by "OnStoreProduct" function in vmcustomplugin.php, line 213. My understanding is that for some reason, at that point, $this->_name is returning "specification"!
Note that when at a later stage the function "plgVmOnStoreProduct" is called, $this->_name correctly returns "displaycontacts". See debug:


vmdebug OnStoreProduct return because key displaycontacts!== specification
vmdebug Displaycontacts.plgVmOnStoreProduct.key ($plugin_param) = displaycontacts
vmdebug Displaycontacts.plgVmOnStoreProduct.$this->_name = displaycontacts


I believe - albeit not sure until I get it to work - that because of this error, "plgVmStorePluginInternalDataProduct" is never being called!

That said, I did manage to find a way around this problem by imploding my values inside "plgVmOnStoreProduct" and then call  "$this->OnStoreProduct". I can conform that like this, in the database table  the selected values have all been inserted separated by a comma. Here is the code:


$plugin_param[$key]['custom_contacts_id'] = implode(',', $plugin_param[$key]['custom_contacts_id']);


I would like to solve the problem I highlighted at the begining ... ie - that $this->_name return "specifications". I looked through the code and did not find any such word. I also based my plugin on the textinput plugin, re-wrote it, re-installed virtuemart (but I am afraid this retains all tables) ... what I have left is to do a fresh installation of joomla, install virtuemart and try again.

Also, please do let me know if what I did is bad - maybe in terms of virtuemart overall design - because I would really like to know more.