I am in the process of extending the wizard functions provided by CTools to cater to the needs of my current project. My plan is generalized enough that it could be used by other modules. My code is raw thus far but I figured it would be worth the time to post what I am doing so I can get feedback as I would be surprised if you hadn't already considered something like this.
In a nutshell, here is what I am trying to do:
* Allow other modules to alter wizards and apply their own forms.
* Extend wizard capabilities to nativley support multiple levels.
My code currently works much like FAPI as you can get a wizard much like a form:
ctools_get_wizard('my_wizard', $param);
Modules can implement hooks to alter the wizard:
function mymodule_wizard_my_wizard_alter(&$wizard) { ..
function mymodule_wizard_alter(&$wizard, $wizard_id) { ..
And wizards can have multiple levels (nested steps):
$wizard = array( // aka $form_info
...
'forms' => array(
// normal form definition
'step_x' => array(
'form id' => 'form_callback_x',
'title' => t('Step X'),
'weight' => 0,
'type' => 'form', // (default)
),
// group of forms definition
'group_y' => array(
'title' => t('Group Title'),
'type' => 'group',
'weight' => 1,
'forms' => array(
'group_y_step_1' => array(
'title' => ...
'form id' => '..'
),
),
),
);
);
I'm implementing this so that it could be integrated with CTools or live entirely in it's own module. The module provides "wizard" plugins which would allow defining wizards for existing modules.
Anyway, I figured I'd better share to see if there is anything already out there or to see if I may be headed in the wrong direction.
What are your thoughts?
(I can break this into 2 different posts as there are two distinct features, but I wanted to get your general thoughts on both the options)
Comments
Comment #1
merlinofchaos commentedOne complication here is that the $form_info structure tends to get tinkered with a lot before it's used. Maybe a builder function is the right way here, but I'm not sure about it.
Certainly drupal_alter function at the beginning of the wizard would allow wizards to be more easily tinkered with. I hadn't given that a great deal of thought, though, but an alter right there would let you rearrange the wizard nicely.
I'm not sure how well the 'group' steps could easily be implemented. That's going to be quite tricky and I'm not sure there's really that much payoff for doing it.
Comment #2
lee20 commentedYeah I suspect it can be tough but my motivation for doing it was that I wanted to be able to provide a UI similar to that of page manager. I started off trying to replicate page_manager but got lost in the architecture and didn't see how to implement a new "task type".
I'm in the process of implementing the multiple levels right now, and I am basically implementing it similar to the trails in the page manager. It will use the path from menu_get_item to determine the additional arguments as the "active steps".
The builder also accepts a theme callback to allow customizing the output of a wizard so that horizontal navigation can be provided. This navigation makes it tricky as step forms can be required or not required and perhaps this navigation is only visual as if it were clickable it would have to simulate button clicks.
So I guess maybe I should ask is there away to define my own task type for page manager? And does my plan sound completely insane or impossible?
Comment #3
merlinofchaos commentedI've often wanted to abstract page manager to provide a similar UI.
Page Manager isn't just one wizard; each tab is a separate wizard. The tabs are their own system, and then each tab has a wizard attached to it so it can have multiple forms if needed. Putting all of the tabs into the same wizard would probably overload the poor wizard system, which isn't going to be able to handle quite that level of stuff.
Though as I think on it, all the forms get melded together anyway. Hmm. I'll ponder this some more.
Comment #4
lee20 commentedThanks for your time and your thought on this.
When I have something a little more workable I will create a sandbox for it, or I guess I need to figure out if I can create a clone of CTools as a sandbox. Still new to this Git stuff but I really like it so far.
I guess the one thing I am not accounting for within the wizard that is included in the page manager is the "actions" and "subactions" at the top of the UI. I'm not sure if this is something the wizard would need to support natively but it's another thing to consider.
Comment #5
merlinofchaos commentedYeah, all of the actions and subactions in the UI are part of Page Manager's not-at-all abstracted "operations" concept which I sort of threw together when I was trying to figure out how to make the UI work.
You can clone a project into a git repo like this:
There might be a shorter path to all of this, like you might be able to just do one checkout and skip making a 7.x-1.x branch that is tied to the ctools remote branch but this way you can be sure you won't accidentally tie your new branch to the ctools remote.
Once you've got a branch setup, I can do reviews via the sandbox drupalcode.org URL and I can add the remote and do merges, but you do need to make sure your commit messages are good. (If not, I can just squash them, too).
Comment #6
lee20 commentedThanks for the direction. I'm kind of pressed for time so some of my additions may not have much for commit messages as I will probably mass add them. Any modifications I make to existing Ctools files will have good commit message though.
Also, I am working on a 6.x version. I put this request under 7.x as I figured that was best for feature requests.
So I will be cloning ctools/6.x-1.x and we can port it to 7.x when if/when we merge it.
Another thing to mention, I don't have much for administrative UI planned for this. Right now I am trying to integrate wizards with node forms so the wizard module will be providing a node plugin that allows you to override the node forms with a wizard, but this won't do much itself as it will only override the node add/edit form paths and provide a wizard with only a single step. From here, other modules can add their own forms using the alter functions, but the additional forms I will be implementing will be specialized to my needs. Perhaps it can additionally allow you to break out the node structure into separate forms using field groups or another mechanism.
Comment #7
lee20 commentedUpdating the issue meta..
Comment #8
lee20 commented@merlinofchaos
I am having trouble getting the sandbox initialized as a clone of ctools. I added you as a maintainer. Think you could help me get this initialized as a clone of ctools 6.x-1.x?
http://drupal.org/project/1098774
#1098774: CTools Wizard
Comment #9
lee20 commentedYour instructions didn't include instructions for initializing the project to get the [sandbox URL]
So I tried the instructions described here and kept getting an error:
http://drupal.org/node/1053378
Comment #10
lee20 commented@merlinofchaos
Please disregard. I'll get this setup and running eventually!
Comment #11
lee20 commentedGot it. Here is a more complete list of commands I used.
Comment #12
Brandonian commentedSubscribing.
Comment #13
lee20 commentedJust wanted to post and say that I have made some progress on this. So far I have put everything as a submodule of CTools but there would be a number of additions to the ctools wizard which I have contained in the submodule for now. I need to go through and clean it up and add some comments and then I'll commit what I have. It has a start for the multi-level support but not much yet.
Comment #14
lee20 commentedSweet. I just got something that's usable and has functionality packed in. The Wizard module includes a node plugin which overrides node forms with wizards. Initially I only had this as one step but a one step wizard is useless! It hit me to make the node preview the second step so now there is actually some value in the basic functionality.
The code is still a bit messy but I'll start committing to the sandbox.
Comment #15
steveoliver commented+1 @lee20: I really like your idea! Previewing the node in a second step offers the opportunity to separate the content fields from the meta.
I as an author would enjoy focusing on only "content" first, and appreciate the context of preview/diff alongside my commit/revision message, tags, scheduling, etc.
I'll be tracking your repo, for sure. Thanks for sharing.
Comment #16
kenorb commentedRegarding node preview (#14, #15) in ctools, sorry if it's a little off-topic, my code looks like this:
Then my_module_preview_node callback is defined my_module_form_info()
So hopefully some code could be useful.
Comment #17
kenorb commentedDrupal 6 is no longer officially supported. If you think this issue is still relevant for 8.x, feel free to re-open.