Setting customer user data with CRUD object in Woocommerce - php

I'm trying to set a new value for the first_name for a user on woocommerce, i want to do this using the 'CRUD Objects in 3.0' present in the last documentation of woocommerce 3.0.
Só i'm definig the variable:
$wc_current_user = WC()->customer;
This return an instance of the class WC_Customer with has an array of $data with data about customer like $first_name, $last_name, $email, $billing_address array and so on...
i'm trying to rewrite the edit-account.php form and want to submit this data on this object, he provide the getters and setters to do this, but seems the setter ins't working, he is not saiving the data.
I'm doing this:
I have a form with takes the first name from the user, this is working fine, i'm using the ->get_first_name and is working fine.
<form class="woocommerce-account-information" action="" method="post">
<label>First Name</label>
<input type="text" name="first_name" value="<?php echo
$wc_current_user->get_first_name()?>"/>
<button type="submit">SAVE</button>
</form>
The Problema is here, when i try to submit this data using a setter, which in this case is 'object -> set_first_name' and 'object->save()', nothing happens, someone can help me?
Here is my code:
if( isset($_POST['first_name'] ) ){
$wc_current_user->set_first_name($_POST['first_name']);
$wc_current_user->save();
}
//THIS ^ DON'T WORK, do you know what is wrong?
I'm interested in knowing both the old and the new method, if anyone can help me, it will be a great help. Thank you!

You're using the correct method to set the user's first name.
set_first_name() won't permanently save a value on its own. When you've set all the properties you wish to update you need to call the save() method.
if ( isset( $_POST['first_name'] ) ) {
$wc_current_user->set_first_name( $_POST['first_name'] );
$wc_current_user->save();
}
https://woocommerce.wordpress.com/2016/10/27/the-new-crud-classes-in-woocommerce-2-7/
https://github.com/woocommerce/woocommerce/wiki/CRUD-Objects-in-3.0

I find a solution for this problem, when you use object like this you need to use the $object-save() method that Nathan has said plusthe $object->apply_changes(); to submit replace the data on data-base:
public function apply_changes() {
$this->data = array_replace_recursive( $this->data, $this->changes );
$this->changes = array();
}
My working code looks like this:
$wc_current_user = WC()->customer;
if ( isset($_POST['first_name']) ) {
$wc_current_user->set_first_name($_POST['first_name']);
$wc_current_user->save();
$wc_current_user->apply_changes();
}

Related

Gravity Forms custom validation filter

I have a function that processes sales via a third-party service, processes the result and returns an array with the Status "Success" or "Invalid." This sales call is made using the gform_after_submission hook applied to the specific form.
What I need to do is store the "Success" or "Invalid" result in the array as a variable that I can later pass to a function to validate or invalidate the credit card field, using gform_validation hook.
I'm declaring the variable in a function, like so:
function foo {
...code to sell product through API...
$status = $checkoutShoppingCartRequest['Result']['Status'];
}
When I print the variable $status within the function, it is showing either Success or Invalid like it should.
Here is other function where I need to use this variable, passed to gform_validation, which fails every time regardless of Success or Invalid result:
function MBvalidate( $validation_result ) {
$form = $validation_result['form'];
if ( $status !== "Success") {
$validation_result['is_valid'] = false;
foreach( $form['fields'] as &$field ) {
if ( $field->id == '34' ) {
$field->failed_validation = true;
$field->validation_message = 'Your credit card could not be processed.';
break;
}
}
}
//Assign modified $form object back to the validation result
$validation_result['form'] = $form;
return $validation_result;
}
add_filter( 'gform_validation_47', 'MBvalidate' );
I have tried passing the variable a number of different ways, via globals and sessions, etc.
I am new to GF development so I am sure I'm missing something. I'd appreciate any direction.
The gform_after_submission action hook runs after gform_validation.
Anyway, assuming you can find a hook that runs earlier, what I would do is store a unique variable for each submitted form using the Transients API's set_transient() and get_transient() functions. For example you can create a hidden field in every form which you populate with a random ID. Use this random ID as a key to store and retrieve the Success/Invalid result.
$status here is a local variable which has never been defined before you try to use it in if-condition. So, it's always null.
Maybe you missed
$status = $validation_result['Result']['Status'];
or something like this before checking the condition.

Insert DB Value into Form Field

The Question: How do I insert values from a database table (#__mytable) into form text fields (motitle and modescription) which have been rendered from an XML file within the Joomla 3.0 platform?
-
I've been trying for days to solve this "easy" Joomla! based undocumented challenge.
I have followed Joomla!'s guide for Developing an MVC, read most of their out-of-date documentation and torn apart the com_content component but have still no idea how to populate my fields.
I've been playing with $this->form->bind($this->item);.
Below I have included some of my code to show the structure I am using. Please feel free to point out any issues you spot along the way.
Models\Forms\item.xml
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="groupOPTIONS">
<fieldset name="Options">
<field
type="text"
name="motitle"
id="motitle"
label="Title"
description="MY TEXT FIELD DESCRIPTION"
maxLength="255" />
<field
type="textarea"
name="modescription"
id="modescription"
label="Description"
description="MY TEXT FIELD DESCRIPTION"
rows="15"
cols="5"
maxLength="255" />
</fieldset>
</fields>
</form>
Models\item.php
jimport('joomla.application.component.modelitem');
class MagicObjectsModelItem extends JModelForm {
public function getForm($data = array(), $loadData = true) {
// Get the form 'items'
$form = $this->loadForm('com_magicobjects.item', 'item',
array('control' => 'jform', 'load_data' => $loadData));
if (empty($form)) {
return false;
}
return $form;
}
protected function loadFormData() {
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_magicobjects.item.edit.data', array());
if (empty($data)) {
$data = $this->getDBItem(1);
}
return $data;
}
public function getDBItem($pk) {
//Obtain JDatabase static connection
$oDb = JFactory::getDbo();
$oQuery = $oDb->getQuery(true);
$sValueToMatch = $pk;
$oQuery
->select(array('mid', 'name', 'keyword', 'description'))
->from('#__mytable')
->where('mid = "' . $sValueToMatch . '"')
->order('mid ASC');
$oDb->setQuery($oQuery);
return $oDb->loadObjectList();
}
views\item\view.html.php
jimport('joomla.application.component.view');
function display($tpl = null) {
// Initialise variables.
$this->form = $this->get('Form');
$this->item = $this->get('Item');
//Display the view
parent::display($tpl);
}
Views\item\tmpl\default.php
foreach ($this->form->getFieldset('Options') as $field) {
echo $field->label;
echo $field->input;
}
By performing a print_r() on item I can see I have the data, but I need to insert the data into the fields shown.
In case this it's still a problem because the form definition is defining a <fields /> group.
This mean that the form fields will be output as follows:
input type="text" name="[groupOPTIONS][motitle]"
based on the example you give above. If you remove the fields grouping it will probably work. It's annoying though as certain JForm methods only work on groups...
You would probably need to change the way in which the data was being passed into the form if you wanted to keep the fields grouping (e.g. by overloading getItem).
Hope that makes sense...
In Joomla 3, the JForm::bind() method appears to accept either an object or associative array as a parameter. All of the object/array fields are then stored in a protected JRegistry type data member called JForm::$data.
When you're trying to display a form field (by calling JForm::getInput()), the call stack is as follows
JForm::getInput() -> JForm::getField() -> JForm::loadField() -> JForm::getValue()
JForm::getValue() returns a value from the (aforementioned JRegistry) JForm::$data data member. The JForm::loadField() method also passes the default value (defined by the form) to the JForm::getValue() method in case a value in the JForm::$data variable doesn't exist.
In terms of doing this inside a model, you might want to generate a object or assoc array from a database query or table (ensuring that the field names correspond with the field names defined in the form xml) and then pass it to JForm::bind() as a parameter. However, if you are using JModelForm, I think you should only override JModelForm::loadFormData() to pass the object/assoc array to the loaded form.
See : libraries/joomla/form/form.php
Hope that helps :)
Instead of $oDb->loadObjectList(); use $oDb->loadAssoc(); in your getDBItem() function.
Check this - http://docs.joomla.org/Accessing_the_database_using_JDatabase/1.5
Check this also - joomla loadformdata
Hope this will work.

Joomla PHP: Checkbox won't uncheck

Making a simple component. If I save a new record with the box checked, it saves fine. If I go back and uncheck a previously checked item it reverts back to checked. I thought it had something to do with a hidden field, played with putting one of those in manually but that didn't fix it either so took it out.
Here's where I'm at:
An xml snippet:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="1"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="1"
filter="intval"
/>
...
</fieldset>
The edit.php file:
<div class="width-45 fltlft">
<fieldset class="adminform">
<legend>Checkboxes</legend>
<ul class="adminformlist">
<?php foreach ($this->form->getFieldset('checks') as $field): ?>
<li>
<?php echo $field->label; ?>
<?php echo $field->input; ?>
</li>
<?php endforeach ?>
</ul>
</fieldset>
</div>
Also added this towards the end before the form.token:
<input type="hidden" name="task" id="task" value="completion.edit" />
I tried deleting the value="1" in the xml but then I had the opposite problem where the check wouldn't save at all.
Any ideas?
Thanks!
=============================
Edit:
Model:
<?php
defined( '_JEXEC' ) or die;
jimport('joomla.application.component.modeladmin');
class AssessModelCompletion extends JModelAdmin
{
//tells it what kind of record and the prefix
public function getTable($type = 'Completion', $prefix = 'AssessTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
//Load the data into the edit form
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_assess.edit.completion.data', array()); //first try to get the data from the session, not db
if (empty($data)) {
$data = $this->getItem(); //this gets the data
}
return $data;
}
//Stores data in a session in case a field is missed
public function getForm($data = array(), $loadData = true)
{
$form = $this->loadForm('com_assess.completion', 'completion', array('control' => 'jform', 'load_data' => $loadData));
return $form;
}
}
And table:
<?php
defined ( '_JEXEC' ) or die;
class AssessTableCompletion extends JTable
{
public function __construct(&$db)
{
parent::__construct('#__tablename_completions', 'completion_id', $db);
}
}
======================================
References:
https://stackoverflow.com/questions/6964333/joomla-1-6-admin-form-processing-grouped-checkboxes-in-form
Tutorial code is not working any more in Joomla 2.5
http://docs.joomla.org/Developing_a_Model-View-Controller_%28MVC%29_Component_for_Joomla!1.7_-_Part_09#Adding_a_toolbar
So this is a kind of odd situation in that the documentation you list makes it seem that you would have to write no code to handle the checkbox (because as you point out a checkbox is different then checkboxes). But this does not seem to be the case because of the way that html checkboxes are submitted.
A quick overview of this issue and one solution can be found here: http://planetozh.com/blog/2008/09/posting-unchecked-checkboxes-in-html-forms/.
To use this, you would need to get the field's name out of the $field variable (which I'm not sure if it will be easy to access) and then place the <input type=hidden name='name' value=0> before <?php echo $field->input; ?>.
The other method to fix this would be to process the form data during save and override elements. Joomla has a prepareTable function that you could add to your model to edit data as necessary during save. The following example assumes that your form elements are wrapped in a jform array. (Confirm this by looking at the name fields in the html generated and they should be 'jform[checkbox1]')
protected function prepareTable(&$table)
{
$jform = JRequest::getVar('jform'); // load all submitted data
if (!isset($jform['checkbox1'])) { // see if the checkbox has been submitted
$table->checkbox1 = 0; // if it has not been submitted, mark the field unchecked
}
if (!isset($jform['checkbox2'])) { // likewise for other checkboxes
$table->checkbox2 = 0;
}
}
In this case, you would want to keep "value=1" in your xml fields file.
The problem ultimately is that Joomla loads the current data from the database during saving and then binds the posted data over the top of it. Because an unchecked box is not submitted in the post data, it does not overwrite the databases information and is thus not saved.
Although the documentation states that you do not have to do any manual handeling of the checkbox this is not true.
As no value is sent in the $_POST array when a checkbox is not checked the value is not overwritten and thus not saved which makes it impossible to uncheck the checkbox. To fix this you have to write special handling for your checkboxes in your table bind() function like this:
class YourcomponentTableYourview extends JTable
{
/**
* Constructor
*
* #param JDatabase A database connector object
*/
public function __construct(&$db)
{
parent::__construct('#__your_table_name', 'id', $db);
}
public function bind($array, $ignore = '')
{
if (!isset($array['name_of_field']))
$array['name_of_field'] = 0 ;
return parent::bind($array, $ignore);
}
}
As you don't have any model/table code showing, I think you may be mistaking JForm's purpose - it is purely for rendering of the form. You still have to have in your model/table something to handle the array that is returned for multivalued fields.
As Sam Moffat put it:
there is no coupling between the form definitions used to render the data and the models and table structures used to persist them
So I had a lot of fields and wanted to simply loop through them in my edit.php field to keep it clean. While all the answers offered were right they weren't easy to implement - got really messy really quickly, had trouble getting it to work, or couldn't figure out a cleaner way around it. I chewed on this for awhile and then today came across what is basically a field override.
The key:
The standard form field types are located in
joomla/libraries/joomla/form/fields/. You should not store custom
fields there, nor should you have to use this path in your own code,
but the standard types are usually good examples.
The custom field types that belong to your component are usually
located in administrator/components//models/fields. You can specify this or another path in your
code
So, I copied checkbox.php to models/fields. Then, towards the end of the file I added the empty field before the checkbox tag:
<input type="hidden" name="'.$this->name.'" id="'.$this->id.'" value="0" /><input type="checkbox" .....
Now, whenever I need a checkbox the empty field is also written. May not be the most efficient solution but simple to implement and can hopefully help someone else.
[Edit]
As a note, with every Joomla update you would probably need to compare the versions in the core in case there was a change.
I know this is an old question, but the official answer is long winded and I think I have a better solution.
Try setting the default value for the checkbox to 0 rather than 1 in your xml like so:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="0"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="0"
filter="intval"
/>
...
</fieldset>
I just came across your question and tried setting it to 0 as I didn't want to tamper with the core and hey presto it works.
My guess is that Joomla sees no value and thus sets the default instead.

Submit form values using controller and model in magento admin module

I am building an admin module and need to process a form but am having troubles getting the variables to POST and am just redirected to the dashboard. The form looks like this :
<form name="notes" action="<?php echo Mage::helper("adminhtml")->getUrl("foo/index/processnotes/");?>" method="post">
<input type="hidden" name="another_form_key" value="<? echo $this->getFormKey(); ?>" />
I am doing it that way because the secure keys are turned on for admin. It gives me a url like :
foo/index/processnotes/key/4745f5fbb9c168778958d5d4a4c2c0ef/
In the controller I have:
public function processnotesAction(){
$model = Mage::getModel('foo/process');
// I am not sure how I am supposed to send $_POST values here
}
and in Package/foo/Model/Process.php
I would hope to be able to process the POST variables from my form in here but I can not see what is wrong and I am just sent to dashboard.
<?php
class Package_foo_Model_Process extends Mage_Core_Model_Abstract
{
public function noteProcess() {
$test = $_POST['myValue'];
echo $test;
}
}
Update
After reading the answers I wanted to add a bit more of what my real code is doing and how I am using $_POST. I was setting up a simple example to just get the form to post but realizing there are probably many things I am doing wrong in Magento.
$query="INSERT INTO `notes_value` ( `color`, `the_id`, `the_value` ) VALUES ";
$sku = $_POST['color'];
array_pop($_POST);
foreach ($_POST AS $key => $value) {
$values[] = "('$sku', '$id', '$value')";
}
$query .= implode(', ', $values) . ';';
The dream is I could $resource->getConnection('core_write'); to actually insert this into the database but feeling less optimistic with how it is going so far.
Usually when you are getting redirected to the dashboard because your key is not recognised. I normally would use the following syntax
<input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
Also, I would be inclined to disable admin keys to verify whether that is your issue.
Next, never, ever use $_POST with Magento, all variables are accessible (cleanly and securely). POST information is accessible globally (not just in a controller), however you can still set variables in your model from the controller like this:
public function processnotesAction(){
$model = Mage::getSingleton('foo/process');
$model->setData('postdata', $this->getRequest()->getPost() );
}
Then accessing them from your model with:
$this->getData();
$this->getMyPostedField();
Or you could just use this in your Model
Mage::app()->getRequest()->getPost();
Mage::app()->getRequest()->getParam('myargument');
getPost can also take a parameter to fetch a single POST value - but it does not get GET values. getParam will return both GET and POST values alike.
Request params are accessible via the request object, Mage_Core_Controller_Request_Http. Example usage:
$request = $this->getRequest();
$params = $request->getParams();
$someParam = $request->getParam('param_key');
// or $params = $request->getPost();
You then need to set the data on your model and call $model->save().
If your controller extends ActionController, then the preDispatch() function is the one responsible for redirecting you to the dashboard (and checking for valid form key..).
I suggest you put Mage::log debug info into ActionController's preDispatch function, that might help identify what's going on?
I was gonna post a comment, but don't have high enough reputation.
(maybe update your post or comment on the answer that helped you, to see how you solved it (or not))

Symfony - Several form on the same page -> ID issue

I have an issue while displaying several forms of the same model on the same page.
The problem is that with the NameFormat, the fields have the same ID :
$this->widgetSchema->setNameFormat('display[%s]');
Will display
<form class="update_display_form" id="update_display_0" action="/iperf/web/frontend_dev.php/update_display" method="post">
<input type="checkbox" name="display[displayed]" checked="checked" id="display_displayed" />
<label for="display_displayed">test</label>
</form>
<form class="update_display_form" id="update_display_1" action="/iperf/web/frontend_dev.php/update_display" method="post">
<input type="checkbox" name="display[displayed]" checked="checked" id="display_displayed" />
<label for="display_displayed">truc</label>
</form>
And if you click on the second label, it will activate the first checkbox
So I thought I could use the object id to make them unique :
$this->widgetSchema->setNameFormat('display'.$this->getObject()->getId().'[%s]');
But then I can not process the request, since I don't know the name of the parameters.
The best option I found was to set an ID :
$this->widgetSchema['displayed']->setAttributes(array("id" => "display".$this->getObject()->getId() ));
but then I totally loose the connections between the label and the checkbox.
The problem would be solved if I could change the "for" attribute of my label. Does somebody know how to do that ? Or any other option ?
Here's an idea... push a variable to the form class from your action for setting a different name format dynamically:
In your action:
$this->form_A = new displayForm(array(),array('form_id' = 'A')); // pass a form id
$this->form_B = new displayForm(array(),array('form_id' = 'B'));
$this->form_C = new displayForm(array(),array('form_id' = 'C'));
In your form class:
$form_id = $this->getOption('form_id'); // get the passed value
$this->widgetSchema->setNameFormat('display'.$form_id.'[%s]'); // stick it into the name
It's ugly but I'm sure you can come up with something cleaner...
Conflicting inter-form checkbox/label interactions is caused by tag's id/for attributes not by their name attributes.
So there is no need to modify form's widget name format and thus having problem reading submitted data from request object (either by passing request key as form url parameter/hidden input or by looping all form name combinations created in the layout for each form and finding a matching one).
sfForm class has sfWidgetFormSchema::setIdFormat() method for that.
// Creating form instances
$formA = new sfForm();
$formA->getWidgetSchema()->setIdFormat( '%s1' );
$formA->getWidgetSchema()->setNameFormat( 'display' );
... // configure the form
$formB = new sfForm();
$formB->getWidgetSchema()->setIdFormat( '%s2' );
$formB->getWidgetSchema()->setNameFormat( 'display' );
... // configure the form
$formC = new sfForm();
$formC->getWidgetSchema()->setIdFormat( '%s3' );
$formC->getWidgetSchema()->setNameFormat( 'display' );
... // configure the form
// Processing a request data
$form = new sfForm();
... // configure the form
$_formNameRequestKey = $form->getName();
if( $request->hasParameter( $_formNameRequestKey ) ) {
$form->bind( $request->getParameter( $_formNameRequestKey ) );
}
... or just ...
if( $request->hasParameter( 'display' ) ) {
$form->bind( $request->getParameter( 'display' ) );
}

Categories