Re: FormBuilder and frozen dates
| From: | Justin Patrin | 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