Re: FormBuilder and frozen dates
| From: | Etienne van Tonder | Date: | Wed, 07 Sep 2005 02:02:06 +0000 |
| Subject: | Re: FormBuilder and frozen dates | ||
| References: | 1 2 | Groups: | php.pear.general |
| Request: | Send a blank email to pear-general+get-20829@lists.php.net to get a copy of this message | ||
Hi Justin,
Thank you for your prompt and detailed response it is very much appreciated.
I apologise for the lengthy e-mail but these are the only remaining issues
for me. Thanks for all the work you have done with FormBuilder it has saved
me a lot of time.
1. I upgraded to the latest version of HTML_QuickForm which solved the
frozen date problem as you suggested it would.
2. I added my custom callback function for the date which works. One
question it still displays the date/time separators, is there anyway to get
rid of these, it's not a big deal if I can't, eg (--:: is what I get).
3. I upgraded to the latest version of FormBuilder and made the suggested
changes and it seems to work really well. It now only saves what it needs
to, thanks for the change.
4. After upgrading I started getting the following error on my dates:
"array_merge() [<a href='function.array-merge'>function.array-merge</a>]:
Argument #2 is not an array"
I tracked the problem into the following code in FormBuilder/QuickForm.php,
line 690:
if (is_callable($this->dateTimeOptionsCallback)) {
$dateOptions = array_merge($dateOptions,
call_user_func_array($this->dateTimeOptionsCallback,
array($fieldName, &$fb)));
}
which calls the DB_DO code in DB/DataObject.php, line 189:
if ( substr(phpversion(),0,1) == 5) {
class DB_DataObject_Overload
{
function __call($method,$args)
{
$return = null;
$this->_call($method,$args,$return);
return $return;
}
function __sleep()
{
return array_keys(get_object_vars($this)) ;
}
}
In my case it was returning null, which meant the array_merge would fail. I
changed the code in FormBuilder/QuickForm.php to prevent the error:
if (is_callable($this->dateTimeOptionsCallback))
{
$fArray = call_user_func_array($this->dateTimeOptionsCallback,
array($fieldName, &$fb));
if (isset($fArray) && is_array($fArray))
{
$dateOptions = array_merge($dateOptions, $fArray);
}
}
5. Another question if I may, I have a last update date on my form. There is
a trigger that updates this field when an update occurs. This field is a
frozen field on the form. After the save is there anyway to update the value
of this field with the new value in the DB. When the form is redisplayed
after the save it still has the old value.
6. One other problem I have is that I have a form with a "Clear Form"
function, which calls a javascript to clear all the values for all the
fields on the form including the primary key value. This allows the user to
enter details for a new record and when "Save" is selected the record is
inserted. This works fine for DB_DO objects where I do not use the
$fb_userEditableFields array. As soon as I start using the array, the
records are updated rather than inserted. I tracked this down in the code in
FromBuilder.php, line 2448 (this may not be the exact line as I've added the
code you suggested earlier):
...
foreach ($values as $field => $value) {
$this->debug('Field '.$field.' ');
// Double-check if the field may be edited by the user... if
not, don't
// set the submitted value, it could have been faked!
if (in_array($field, $editableFields)) **** Line causing the
problem
{
if (isset($tableFields[$field])) {
...
As my primary key is not in the $fb_userEditableFields array it never gets
reset with it's new value(ie ""). I've changed the code to be:
+ $pk = $this->_getPrimaryKey($this->_do);
foreach ($values as $field => $value) {
$this->debug('Field '.$field.' ');
// Double-check if the field may be edited by the user... if
not, don't
// set the submitted value, it could have been faked!
- if (in_array($field, $editableFields)) {
+ if (in_array($field, $editableFields) || $field == $pk) {
I'm not sure if this is a valid solution for the problem, if not can you
suggest an alternative.
Regards,
Etienne.
----- Original Message -----
From: "Justin Patrin" <papercrane@gmail.com>
To: "Etienne van Tonder" <evt@infoware.com.au>
Cc: <pear-general@lists.php.net>
Sent: Wednesday, September 07, 2005 3:16 AM
Subject: Re: [PEAR] FormBuilder and frozen dates
On 9/5/05, Etienne van Tonder <evt@infoware.com.au> wrote:
> There are two issues with frozen dates, I wonder if other people have
found
> the same problem. Maybe I should be doing something I'm not??
>
> 1. If I use the $fb_userEditableFields array and I exclude a date field
from
> the list (ie I want it frozen) the date field is never frozen.
This is a problem with the groups in HTML_QuickForm. It has been known
for quite some time now. I believe it has been fixed in CVS but I
haven't tested the fix yet. See the bug I posted:
http://pear.php.net/bugs/bug.php?id=3211
> 2. If the date in the DB is NULL the date always defaults to today's date.
> This may be ok for editable dates but should not happen for frozen dates.
> The problem is that in the function _date2array, if the date passed to it
is
> null it will return today's date.
This could be very easily fixed by using your own date callback. Something
like:
function myDate2Array($date) {
if ($date == null || !strlen($date)) {
return array(); //you may need to add empty keys here for all of
the date format chars
} else {
return DB_DataObject_FormBuilder::_date2Array($date);
}
}
Then set the callback option:
$fb->dateFromDatabaseCallback = 'myDate2Array';
Or
$do->fb_dateFromDatabaseCallback = 'myDate2Array';
>
> Another question which may be related to DB_DO, is there a way I can
prevent
> certain fields from being updated when the form is submitted. I don't want
> my frozen fields to be sent to the DB as they may overwrite new values.
>
Updated how? DB_DataObject will normally update all fields that it has
for the table. However, with FormBuilder this shouldn't really be an
issue as it won't set fields in the DO which are not set as user
editable. Even if a different value was sent in the hidden input value
it won't be set in the DO and hence not sent to the DB. See line 2447
in FormBuilder.php. It is possible to have DB_DO only update the
fields which have been changed but this requires you to pass in a copy
of the DO with the values it used to have. FormBuilder does not
currently do this although it would be a fairly simple patch. Here's a
simple patch which should do it. If it works for you I'll check it
into CVS:
diff -u -r1.205 FormBuilder.php
--- FormBuilder.php 26 Aug 2005 17:39:58 -0000 1.205
+++ FormBuilder.php 6 Sep 2005 17:15:21 -0000
@@ -2439,7 +2439,7 @@
if (!is_array($links = $this->_do->links())) {
$links = array();
}
-
+ $origDo = clone($this->_do);
foreach ($values as $field => $value) {
$this->debug('Field '.$field.' ');
// Double-check if the field may be edited by the user...
if not, don't
@@ -2571,7 +2571,7 @@
$this->debug('ID ('.$pk.') of the new object:
'.$id.'<br/>');
break;
case DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEUPDATE:
- if (false === $this->_do->update()) {
+ if (false === $this->_do->update($origDo)) {
$this->debug('Update of main record failed');
return $this->_raiseDoError('Update of main
record failed', $this->_do);
}
--
Justin Patrin