How to preprocess form data?

690 views
Skip to first unread message

Mike Pearl

unread,
Feb 27, 2013, 2:55:18 PM2/27/13
to joomla-de...@googlegroups.com
I've created a form with a text field that will NOT be stored in the Table.  It's an OAuth access "code".  Once the user saves the record, I need to grab that "code" and exchange it for access  "Tokens".  In the end, I'll be tossing out the "code" field, and saving a few (hidden) fields.

I thought the place to exchange the "code" for the "tokens" was in JModelAdmin::prepareTable().  But Joomla is not passing $table->code back.  is prepareTable() the right place to exchange the "code" for the "tokens"?  How can I get the value from the "code" form field?

Thanks!

Mike

Mark Dexter

unread,
Feb 27, 2013, 5:05:20 PM2/27/13
to joomla-de...@googlegroups.com
If I'm understanding you correctly, I think you want to look at the
bind method. Mark
> --
> You received this message because you are subscribed to the Google Groups
> "Joomla! General Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to joomla-dev-gene...@googlegroups.com.
> To post to this group, send an email to joomla-de...@googlegroups.com.
> Visit this group at
> http://groups.google.com/group/joomla-dev-general?hl=en-GB.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Neo314

unread,
Feb 27, 2013, 6:54:13 PM2/27/13
to joomla-de...@googlegroups.com
I'm still a novice here, so please forgive me if I am off base, but aren't you authorizing the code and getting the token through AJAX? Couldn't you override the save process in the controller, Get the request data, have a function in your model send the code and get the token and update the request data with the token, then proceed with the parent::save(); Name the code field the same as your databases token field and before the data is saved you change it from the code to the token. If that worries you because you might save the code or because it might be populated with the token at a later time, name the code something different and have an empty hidden token field on your form.

That is what I have been doing, though not with any external requests. It's pretty simple though.

I did a little experimenting, and it seemed if the field was not on the form, the data would not save when I updated the request array with a value, so a field seems to be required. In other words, using your case, if I have a code field and no token field; grad the request array and add $data['token'] = xxxx to the array and push it back into the request, it still does not save in the db, but if there is a token field, it works fine.

Mike Pearl

unread,
Feb 27, 2013, 8:34:52 PM2/27/13
to joomla-de...@googlegroups.com
Mark,

Thanks for the reply.  I'm not clear on what and when the bind method comes in to play.

Do I have the $data from the form in the bind method ... meaning the 'code' the user entered in the form field?   Do I have the ability to add data to the for $data before its saved?

Mike

Neo314

unread,
Feb 27, 2013, 8:55:56 PM2/27/13
to joomla-de...@googlegroups.com
Again, I'm a bit of a novice at Joomla programming, but yes. I've also been working in the backend mostly, but I believe it should work the same way. You override the save process in the controller. Get the request data (as an array). Change the request data. Set the request data with your modified array. Then call parent::save(); You could also complete the save process yourself and not call parent::save();

Neo314

unread,
Feb 27, 2013, 9:09:12 PM2/27/13
to joomla-de...@googlegroups.com
P.S. For extra style points, code any significant processes for modifying the request data (like exchanging the code for the token) in the model, and call the model from the controller in the controller save function override like

class MycompControllerMyview extends JControllerForm
{
public function save()
{
$model = $this->getModel();
$model->getOauth();
return parent::save();
}
}

and the model would have the function  getOauth() which would get the request data, modify it and replace the request data with the modified information. Since the request data is modified, you don't have to return anything back to the controller. The modified data would be read and saved by the parent save process. If you wanted to error out on a failed process, you would need a return T/F from the model.

Remember as far as I can tell, the parent save function will not save a field that is not in the original form.

I have been working with a set of parameters for a javascript injection. I save the parameters in a single comma separated string, but the admin form has them broken out to a bunch of different elements (textbox, select, etc.). I grab the data before loadform and parse the string into values for all the form fields that do not have database columns. I have a hidden field on the form for the db column that holds the string. On submit, I grab the request data, process all the fields into a comma separated string and set the value of $data['myparams'] to that string.

The request values for all the fields that don't match a db column are discarded during the save process, and my modified string value is saved.

Mark Dexter

unread,
Feb 27, 2013, 11:31:17 PM2/27/13
to joomla-de...@googlegroups.com
@Mike: Check out the bind() method of
administrator/components/com_weblinks/tables/weblink.php. It overrides
the parent bind() method and does whatever special processing is
needed. You have an array of the values for that database row. In the
weblinks, it converts some of the columns from arrays to JSON strings
(via the toString() method of JRegistry) to that they get saved to the
db as JSON strings. I use com_weblinks a lot as a guide for how to do
stuff and what things to do where. Mark

Mike Pearl

unread,
Feb 28, 2013, 2:40:46 PM2/28/13
to joomla-de...@googlegroups.com
Mark,

bind() is a JTable method.  Maybe I'm misguided, but I think I need something in the model.  Why? Because it's not a guaranteed success.

The user see's a single field in the form:  'google_code'.  I've required="true" in the form.xml file, so validate() will complain if it's blank.  Still a lot can go wrong that I have to handle before we get into the table.  If they give me a bad code, I'll need to kick them back to the form and tell them the code is garbage.  If they wait too long the code will expire - again, I'll have to kick them back to the form and ask them to get me a new, fresh code.

I think I need to:
  1. Run the submitted form fields through validate() to make sure the code is there (maybe a little more checking, I'm not sure)
  2. Grab the code and send it to Google's API to get the Token (and other stuff) - THIS IS MY ISSUE, I think it's best to do this in the model, but I'm not clear on what method would give me the form $data and allow me to remove the 'google_code' field and add 'google_response' field before it goes on it's merry way to JTable.
  3. Handle Google complaints if there are any - JError::raiseWarning() something useful and send them back to the form.
  4. Toss out the 'google_code' and add google's JSON response to $data
  5. Call JTable to store the record with Google's response.
Thanks again!

Mike

Mark Dexter

unread,
Feb 28, 2013, 2:58:28 PM2/28/13
to joomla-de...@googlegroups.com
No problem. You might look at the save() method of
libraries/legacy/controller/form.php to see how we do a save in core.
Good luck. Mark

Donald Gilbert

unread,
Feb 28, 2013, 3:07:39 PM2/28/13
to joomla-de...@googlegroups.com
At what point are you trying to preprocess the data? There is a method in JModelForm called preprocessForm() that takes a JForm $form, $data, $group arguments. That's typically where I do it: https://github.com/joomla/joomla-cms/blob/master/libraries/legacy/model/form.php#L219

The other option is to use a plugin and hook into the onContentPrepareForm hook, but that's a little more complicated to do than using preprocessForm(), especially if you are building a custom component and can edit your models.


Mike Pearl

unread,
Feb 28, 2013, 5:15:36 PM2/28/13
to joomla-de...@googlegroups.com
Thanks.... My apologies for not getting it... I do appreciate the help.

I've added this code in the models/authorize.php file, which handles the form.

protected function preprocessForm(JForm $form, $data, $group = 'optimizerpro')
{
if(is_array($data)) {
if($data['code']) {
require_once JPATH_COMPONENT.'/helpers/gaapi.php';
$gaapi = new GoogleOAuthAPI();
$data['code'] = $gaapi->getAuthentication($data['code']);  // the getAuthentication() method returns Google's json response.
}
}
parent::preprocessForm($form, $data, $group);
}

This is NOT WORKING.  I have two issues:

1) Joomla calls this method a bunch of times, sometimes $data is an Object, other times it's an array.  I used the two if statements so it only runs when we actually have  a value in $data['code'].  This doesn't seem right - why does it flip between Object and Array?  Is there a cleaner way to do this ONLY when the form is saved with something in the 'code' field?

2) the updated $data['code'] value is lost when Joomla leaves this function - how can I change the value of the 'code' field?

Thanks!

Mike


Don

unread,
Feb 28, 2013, 7:10:47 PM2/28/13
to joomla-de...@googlegroups.com
Put an & before $data in the method declaration to make it a reference instead of a copy. 

As for your other issue, the way you are doing is fine. Good job!

Sent from my iPhone
Reply all
Reply to author
Forward
0 new messages