Suppose we want to have a webform per-event node that contains event-specific registration information that isn't appropriate for storage in the user profile.

Currently the core profile.module adds its form fields to the attendee info form, those values are inserted into the $_SESSION and processed when the order is submitted. This is all hard-coded. Let's make it possible for any module to add its form elements to the attendee info form and make it easy to have the right code run at the right steps in order processing.

hook_form_alter makes it possible to add form elements, but I'm not sure whether we want to require an entire module, as opposed to a small include file, for each implementer of a new hook. Also, we're not using the submit function for this form to process the submissions. Rather, we place it's data into $_SESSION and process it when the order is submitted. While other modules could potentially get away with using hook_order to process submissions, it would be nicer if they could have their code run as part of uc_signup's order processing. This would be easy to implement by passing the uc_signup session data to each module that implements hook_uc_signup_order_submit() or similar.

Then, #527700: Optional Content Profile support, and make core profile optional as well would be implemented simply by implementing this api function and form_alter on behalf of profile (and content_profile) modules.

Comments

recrit’s picture

I agree this needs a complete revamp look. My patch in #527700: Optional Content Profile support, and make core profile optional as well was really just a work around so I could implement the module on a client that was not using the profile module.

Independent of other user profile modules approach:
The signup module already has API to have form data specific to just the signup node. Look in (signup/theme/signup_form.inc) at the function theme_signup_user_form($node). This is really meant for themes to add in their own fields. This is where signup adds in their default fields of Name and Phone number. The form can be altered at the module level with hook_form_signup_form_alter and adding fields to $form['collapse']['signup_user_form']['signup_form_data']. This data is stored on the signup node and not the user. However, altering the form alone only provides a single signup at a time.

The main signup function signup_sign_up_user($signup_form, $notify_user) looks for this extra data in $signup_form['signup_form_data']. uc_signup already spoofs this $signup_form argument, but only sends the uid and nid to perform the sign up. uc_signup could use $signup_form['signup_form_data'] to store other data collected either in uc_signup custom forms or somehow leverage the existing signup forms which already provide hooks for developers to add in custom fields. uc_signup could render the signup form for each sign up in a similar way that it currently does with the profile form.

It would be nice if product attributes could somehow be worked into the per signup forms. For example, an event that has a meal selection attribute. Then each signup could have a different meal selection. Not really sure how to make that work since changing attributes makes it a different "product" with different skus.

[Off topic from form improvements]
In your post you mentioned using the $_SESSION and the data stored in it gets processed on order submit, so that got me thinking on this also.
Currently uc_signup hooks on order submit which makes sense in the normal order flow, however, the issues with PayPal seem to arise because when returning from PayPal (as with WP Standard) they go directly to checkout/complete which skips over submit. The order could be caught on hook_uc_checkout_complete, but this is too late. If any errors happen in the signup processing, the customer has already paid but isn't signed up. Regular checkout form validation usually takes place in the "process" operation of the callback for your hook_checkout_pane. In the "process" operation, you could validate all inputs, create new users if needed, and create the temporary signups. Then it doesn't matter what happens after that point such as going to PayPal. Once payment and the order is completed, uc_signups conditional action would still fire and trigger uc_signup_mark_paid to make the signup permanent.

ezra-g’s picture

"look in (signup/theme/signup_form.inc) "

Yes, I'm aware of the signup form. It's an intentional decision in UC_Signup not to use that form, in order to streamline the attendee info collection process. The signup.module form as some known drawbacks, including that it stores data in a serialized array in the database, making it hard to query. That's one reason why it would be helpful to be able to collect profile information or webform info.

joachim’s picture

It has an API but using the theme layer is evil and wrong!
I'm working on something better here: #29568: Flexible number and type of fields, which would be in a 6--2 branch of signup.

ezra-g’s picture

joachim’s picture

I'm thinking it might be more logical to provide signup-profile and signup-content_profile integration separately and independently of signup-ubercart integration, all with the new signup form API.
In which case, #29568: Flexible number and type of fields needs work so more than one form can be included.

ezra-g’s picture

On a practical level, how would you go about refactoring the current custom uc_signup checkout workflow to integrate the signup form?

ezra-g’s picture

Also, that wouldn't make it possible to process the submitted information and prevent it from being stored if payment fails, or causing payment to fail if the submitted information somehow fails to validate after the order has been submitted.

joachim’s picture

Re: 7
Signup has a lot of hooks I've not yet properly looked into. From my cursory glance at them I am guessing they are observer hooks (as in they allow implementing modules to act on events), but since we are changing API anyway we could design something that allows implementing hooks to allow or deny signup. This would also have applications for modules that seek to implement more complex reservation systems (such as seating plans or something perhaps?).

Re: 6
I've not looked at that yet!
This is purely guesswork, but we need to either intercept the form submission with the information the user has entered, stash it, take a round trip to Ubercart and get the payment, then come back and give Signup the stashed data.
Or we need to alter Signup's system completely. It currently allows for the form to either be on a tab or in the node body. We could implement a third system where the form is only accessible to the user once they have paid. So you'd see the Ubercart 'add to cart' button, and following the UC procedure would eventually grant you access to the node's tab. This would make sense for subsequent alterations to signup data.

I'd like the API I'm working on for Signup to allow whatever it is this module needs -- my patch over on that other issue is only a first draft, so let's keep discussing it, rip it up, rewrite it, etc! :)

dboulet’s picture

Interested in this as well.

joachim’s picture

Re: 6
On reflection, I think maybe what we should aim for is neither of the two systems I described!
Rather, allow the user to sign up, but flag the signup as being temporary.
Then allow other modules (in our case, uc_signup) to process the signup (in this case, take payment) and at some point fire an API function to enable the signup. At this point, the signup is considered complete and live.
A temporary signup expires: perhaps a couple of hours, or even maybe weeks if UC is set up to accept cheque payments.

This way round means that a user gets to book their seat / ticket / whatever when they actually get to the site and enter their data, and they are allocated a place.
The other systems I described in #8 could mean a user hands over cash and then finds that users who were quicker to process payment have taken the last places!

About to post a big patch at #29568: Flexible number and type of fields by the way :)

iva2k’s picture

subscribe

carwin’s picture

subscribing.

joachim’s picture

Update: the code over at #29568: Flexible number and type of fields is now working live on several sites.

> Also, that wouldn't make it possible to process the submitted information and prevent it from being stored if payment fails, or causing payment to fail if the submitted information somehow fails to validate after the order has been submitted.

Signups get cancelled if the user removes the product from their cart; I've not looked at handling the case where payment fails. What doe Ubercart fire when this happens?

socialnicheguru’s picture

Does this allow for content profile to be used with signup for ubercart?

jhedstrom’s picture

Status: Active » Needs work
StatusFileSize
new10.56 KB

Here's a patch that needs a lot of work. In an attempt to lay the groundwork for an eventual API, it does the following now:

* Adds 2 new modules, uc_signup_profile and uc_signup_cp (for content_profile)
* Moves hook_requirements into relevant .install files
* Moves most core-profile-specific code into uc_signup_profile
* Provides update hook to enable uc_signup_profile for existing installs as this is an assumed dependency for existing sites
* Adds very limited integration with content_profile (this needs a lot of work--nodereference and filefields don't work atm)

This bit needs some thought:

/*
 * Get the profile fields required on user registration.
 */
function uc_signup_profile_form() {
  // TODO Generalize this...perhaps a hook?
  if (module_exists('uc_signup_profile')) {
    return uc_signup_profile_profile_form();
  }
  elseif (module_exists('uc_signup_cp')) {
    return uc_signup_cp_profile_form();
  }
}


jhedstrom’s picture

StatusFileSize
new10.62 KB

That last patch broke this for install profiles. Here's the same patch with slight tweaks to hook_requirements (when these get moved to .install, they are run on a Drupal install, so they must return an array).

socialnicheguru’s picture

I tried it and it seems to work.

I can have multiple content profiles. How do I select which one I want to use for signup?

istryker’s picture

Patch fails when applied to beta5 supported version. and fails on the sept 25th dev file (but only the .info file). Looks like you created this patch on a dev version before sept 15th as there was a dependency added to the info file.

jhedstrom’s picture

StatusFileSize
new10.62 KB

Here's a patch that applies cleanly to the latest dev version.

jhedstrom’s picture

StatusFileSize
new10.74 KB

Re-roll that adds a placeholder node to $form_state prior to calling content_profile_registration_add_profile_form (this is needed because otherwise non-privileged users were being redirected to their own content profile when trying to register other users).

ambereyes’s picture

Patch worked for me in general, but I am not sure what I need to do to use fields from content profile. Some explanation would be helpful.

scotwith1t’s picture

subscribe

xeraseth’s picture

I also was able to patch (was an error when it was trying to remove profiles as a dependency for uc_sign.info), but I went in a manually patched that part), but am unable to find where I connect a Content Profile to a signup enabled Content Type

socialnicheguru’s picture

I am trying to apply this patch to the newest version of dev but have lots of errors.

Can this be rerolled?

artis’s picture

StatusFileSize
new79.2 KB

This reroll should work again 6.x-1.0-beta6

zdean’s picture

subscribe

socialnicheguru’s picture

Will this be officially part of the uc_signup module? Will this be it's own add-on module to uc_signup?

I prefer using content_profile over core profile for a number of reasons but I hate having to find this patch everytime a new uc_signup comes up.

I fear that the patch will not be compatible in the future.

kclarkson’s picture

I understand that this is mostly for uc_signup, but what about just a signup_content_profile module?

Basically I have one (content) profile that has conditional fields and would like to include that information on the signup so when we export the list the additional fields show. example: Do you have special dietary needs? If answered yes a selection of different types drops down. Well by using the profile fields they "have" to answer everything.

The reason content profile is so key is that it uses cck and you can have the flexibility of default values and conditional fields.

In addition, if content profile module was created a person only has to only fill out their profile fields once and they can signup for various events by just logging in and hitting the signup button and all of their information would be populated.

tevih’s picture

subscribe

tevih’s picture

I'm going to wake this sleepy post. :)

Has this been included in latest releases?

socialnicheguru’s picture

It hasn't been included.
Can it be?

EDIT:

I get this when I apply patch 20 above
http://drupal.org/comment/reply/623900#comment-3663728

I hit the signup button
I enter an email
press enter
taken to the content profile page
I get:
warning: Cannot use a scalar value as an array in /uc_signup/uc_signup.module on line 438.
warning: Cannot use a scalar value as an array in /uc_signup/uc_signup.module on line 439

here are the lines in question:

 $form[$mail]['profile'][$group][$key .'_'. $mail]['#default_value'] = $default;
              $form[$mail]['profile'][$group][$key .'_'. $mail]['#parents'] = array('profile', $key .'_'. $mail);
ambereyes’s picture

Status: Needs work » Reviewed & tested by the community

This needs to be part of the recent release of uc_signup instead of constantly re-rolling the patch.

tevih’s picture

agreed