Re: FormBuilder and frozen dates

From: Date: Wed, 07 Sep 2005 02:38:31 +0000
Subject: Re: FormBuilder and frozen dates
References: 1 2 3  Groups: php.pear.general 
Request: Send a blank email to pear-general+get-20830@lists.php.net to get a copy of this message
On 9/6/05, Etienne van Tonder <evt@infoware.com.au> wrote: > 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). Yes. The dateElementFormat option. http://opensource.21st.de/23.html#A8 This will change it for everything, though.... > > 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. Do you mean that you applied the change I suggested? As I said, I haven't comitted that yet. > > 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); > } > } Ah overload....what a wonderful feature. NOT! Seriously, overloading has caused far more trouble than it should have. Are you using the overloading features for anything? set/get functions which you haven't defined perhaps? If not I suggest turning overloading off for DB_DataObject. If you're using PHP4 I suggest turning it off whether or not you're using it. It breaks pass-by-reference in functions. Alternatively you can fix this by setting (date|time|dateTime)OptionsCallback to something not callable, like null. > > 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. No. FormBuilder sets the default values on the form when it is being created. In addition, if this is a trigger in the DB itself even DB_DO won't have the new value. If it's a DB_DO update() override you could set the value yourself before displaying. If it's a backend DB trigger you'll need to requery. Or you could just fudge it and display the current date/time. > > 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. No, I don't think that's a valid solution. An update form is an update form. If you pass a filled-out DO to FormBuilder it's going to assume you want to update rather thna insert. You could get around this by adding a hidden field to your form and having your "Clear Form" JS set it. Then check that value and set the PK to "" before processing. > > > 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 > > -- Justin Patrin

« previous php.pear.general (#20830) next »