Re: FormBuilder and frozen dates

From: 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

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