I'm using the ctools multistep form code in a couple of places in a project, and would like to branch the user's path through the form. That is, in step 1, I get some stuff from the user that allows me to determine that the user should be sent to either steps 2a, 2b, and 2c, or 3a, 3b, and 3c. I've been looking but haven't yet found anything out there about this; are branching multistep forms in fact possible with ctools?
Yes, branching logic can be done.
If your validation/submit handler for step 1 sets
$form_state['clicked_button']['#next'] = '2c, your next step will be 2c.
There are a few gotchas, which may or may not surface depending how your forms are intended to be used, whether they allow stepping backwards, etc.
All your steps should at least be in
$form_info['forms'] so the wizard knows how to load them.
Note however, that if step 2c is not in
$form_info['order'], the default "trail" generated by the wizard will not have any of the steps highlighted as it can't figure out where 2c fits in. Likewise, the next/previous steps around 2c may not be the ones you intended if 2c is not listed in the normal flow order.
The wizard basically pre-populates
#next on your buttons based on
'$form_info['order'], and then pushes that value into
$form_state['redirect'] in its own submit handler, so you have complete control of which step is next. You could manually override
$form_state['redirect'], but the wizard should be able to manage it for you.
If your step progression is basically linear but you only want to "skip ahead" based on the selection in step 1, this works fine as you can simply add all steps to
$form_info['order'] in your page callback (or where you defines
$form_info) and doing the next/back logic in your validation/submit handlers. The user will see all steps listed in the "trail" but may skip some depending on your conditional logic. (The back button also has
#next set to say what it goes back to.)
If your step progression is truly branching and a fixed order including all steps would not make sense, I would recommend to hide the trail and re-implement it yourself using the logic which determines which steps go in which order.