CiviCRM - Placeholder Participant Names
- Tags:
After finishing a chunk of changes for a client to make changing registration names after submitting your form, I then had to tweak things further.
As It stands I haven't yet solved the problems that arose. I posted my original article on civicrm's website but I have now included it below. After the article I will provide my current problems, questions and solutions.
Article
I recently finished writing an addition to the events system that will allow pa's etc to book places for people to events and then return at a later date to confirm the names. As far as I know, this is in progress for v2.3 but basically I need it now. Apart from some testing the system should work without too much trouble.
There is only one issue that will perhaps need addressing and that is anonymous signups. As far as I know, CiviCRM will create a new contact record for the person booking if need be and the existing system is preserved so things should work fine. There is an extra button which will make this system work on additional participant pages. Over the next few days I'll test this with v2.2 and see if it is worth getting into the core.
How did I do it I hear you say. Well make yourself comfy and I'll tell.
At the heart of it is an extra button on the additional participant pages. It says something like 'Just reserve place' and I check for this in postProcess() for the form. I also make sure the amount field IS required rather than ignoring it like you do for a skipped one. Then in AdditionalParticipant->postProcess() I set the email of the skipped participant to the same as the booking contact.
I made a small change to CRM_Event_Form_Registration->addParticipant so that the booker's contact_id can be added multiple times to an event. After that it was a case of providing a new link on the EventInfo page to the register update page I created which allowed you to only change the email addresses of your additional participants. Any new emails have a contact created for them and the record in the civicrm_participant table is updated to reflect the new id.
That about sums it up really. I think there may be a little checking I need to do with the change I made in addParticipant to make sure a user can't force extra participants in by revisiting the same page. Other than that, it seems to work.
I have created a patch so this can be tested. The patch should work against the 2.1 branch from the subversion repository but there's a good chance it will work with the tarball too. Obviously this will change files so when patching, please make sure you BACKUP FIRST. You can see the files altered from a quick scan of the file.
I made the patch against the core files so if you have tailored them to suit in a custom directory you might want to apply the changes manually.
note
This patch will NOT make the menu item it needs. You'll have to do that manually I'm afraid, in the database. The path in use is: civicrm/event/updateregister with the usual query string e.g. id=2&reset=1&action=preview will get you event 2 in test mode.
File civi_2_1_delayed_participants.patch
Current Status
I need to check the form when submitted. Rather than adding the new email into the system as a contact if it doesn't exist, I need to ask for a name in these cases. I thought it wouldn't be that hard but it is proving rather tricky.
I've tried working with the elements in a group and failed miserably after several hours of trying. I now have the items as individual elements. I can set errors on these using a formRule. I would have thought that I could get the error by just using element->getElementError() but this draws a blank and so is the _errors array for the form.
I now have it that an error is set using setElementError() which may not be needed soon. I also store the names of the failed elements in a session variable. Then when rebuilding the form, I check whether it has been submitted or not and if so I can check for the error each time I put an element into the form.
Wish it was easier.
Update
The situation as it stands now is; it's working. It's not pretty but it does the job. I don't know why it took me so long to work out what I was doing wrong but to clarify I'll go through the form lifecycle for a sec.
When a form is built methods get called in order:
preProcess -> buildQuickform -> setDefaultValues -> addRules -> display()
The display method is that of the QuickForm class.
This works for any form and when a form is submitted the form is rebuilt, just the same as it is in drupal. Here's the sequence:
preProcess -> buildQuickForm -> setDefaultValues -> addRules -> validate -> postProcess
With this in mind, if a form does not validate things go like this:
preProcess -> buildQuickForm -> setDefaultValues -> addRules -> validate -> display()
At the moment there is no easy way of doing something to the form AFTER it has failed validation because you build the form 3 steps earlier and errors are caught and highlighted later on.
My solution is ugly and I'm not proud of it but I pass in the form to the validation method and make changes there if I need to. Very hacky and if I can come up with a more elegant solution then I certainly will document it here or somewhere on this site.
I think perhaps a hook would be nice, especially if it was optional. Similar to the #after_build or #pre_render hooks from drupal.
In the meantime, there are other things I need to build/fix.
- Printer-friendly version
- Login to post comments