Closed (fixed)
Project:
Drupal core
Version:
x.y.z
Component:
base system
Priority:
Critical
Category:
Task
Assigned:
Reporter:
Created:
23 Aug 2005 at 11:34 UTC
Updated:
3 Mar 2011 at 11:03 UTC
Jump to comment: Most recent file
This is the first check in of the new forms api code.
The system has been designed to co-exist with the current forms api, and is contained in a new
include file (includes/form.inc).
Forms are now defined in their component arrays, similar to how menu items are defined.
example :
$form['body'] = array(type => 'textarea', default_value => $node->body, cols => 60, rows => 60);
Elements can also be nested, and the $edit follows this definition. For instance :
$form['author'] = array(type => 'fieldset', title => t('Authoring information'), collapsible => TRUE, collapsed => TRUE, weight => -1);
$form['author']['name'] = array(type => 'textfield', title => t('Authored by'), maxlength => 60,
autocomplete_path => 'user/autocomplete', default_value => $node->name, weight => -1);
All the properties used are defined as constants, and are documented for each of the elements, and individually.
| Comment | File | Size | Author |
|---|---|---|---|
| #149 | watchdog.module.patch | 829 bytes | Tobias Maier |
| #147 | contact-forms-api.patch | 19.52 KB | asimmonds |
| #143 | forms.tar_2.bz2 | 72.88 KB | adrian |
| #140 | form_5.inc | 33.27 KB | chx |
| #137 | forms.tar_1.bz2 | 72.16 KB | adrian |
Comments
Comment #1
adrian commentedA patch for node.module, blog.module and taxonomy.module that changes them to use the new form format. This patch is very far from complete, but I wanted to get the code out so that i'm not working alone anymore.
Comment #2
adrian commentedThe actual patch =)
I forgot to mention, this adds a new hook .. namely hook_elements, which allows us to define the defaults for the elements (ie : cols and rows for textareas) meaning they don't have to be defined for each of the elements.
Comment #3
chx commentedA few notes from my conversation with adrian.
valid => array('integer', 'uid')for this to work you needfunction valid_integer($element)andvalid_uid($element).$extrafor form_select is legacy and really needed.Comment #4
fagoi really like this approach.
further i'd like to see the possibility to define an additional class to a form element, which is currently not working. so we 'd have to bring _form_get_class() and drupal_attributes() together.
Comment #5
adrian commentedthat works already.
Although I am considering just adding a class property ...
ie:
The fact that this is done via arrays, it means that the developer can add classes as he or she sees fit.
Comment #6
fagoreally?
i don't think so.
e.g.
so we will end up with two class attributes, which won't work and isn't standard compliance.
your css property idea would be ideal imho.
Comment #7
nevets commentedMinor point on #5 and #6, when accessing an associated array like
if the key is a string it should be enclosed in quotes, i.e.
(This is from the PHP documentation.)
Comment #8
moshe weitzman commentedDoes this API affect form validation also? Thats the vague impression I had in my head, but I don't see any validation changed in node or taxonomy modules. perhaps that part is coming next.
There are reasons to love this patch. But one thing I don't like is the movement toward arrays and away from functions. Modern editors and IDE's offer function tips and function completion. These are huge time and brain savers. They are great for newbies and for experts. It is so helpful to just type 'form_sel', press tab, and have form_select('title', 'name', 'value', 'options') printed for you, with all the arguments. When you define forms in an array instead of functions, as proposed in this patch, you lose a lot of developer productivity and friendliness for newbies. Developers are also more prone to mistakes this way since the editor can't guide them along.
This is the sort of advantage that means nothing to the many people who just use a plain editor, and means everything to IDE users. Maybe someone can think of a way to keep the flexibility without losing IDE productivity.
Comment #9
adrian commentedThe api has a drupal_validate_form() function, which does the following validation :
It steps through each of the elements, and executes any of the valid properties. An example would be valid => 'username'.
It then calls valid_username($element), which can check for errors.
It then calls $form_id_validate() , which can check for errors between form elements.
It then (optionally) calls $callback_validate(), which allows you to have unique form id's , similar to how the example does the node form.
You could create a function $type_node_form_validate(), to validate only that form, or a theme_$type_node_form() to theme that form differently.
An example of where this would be used is for CCK, where it will have a single callback for all nodes created by it.
Errors are flagged using form_error($element). It's different from form_set_error, in that it also sets the error property of the element, which I think is more practical than using the globals.
Regarding the IDE discussion, I am on the fence about that, but definitely leaning towards preferring the arrays over the function calls. I think that the menu system has proven itself, and that it's better to be consistent.
The plan for 4.7, is to leave the current form api in , so that all contrib modules don't need to be ported, but to switch core over to the new form system anyway, so for the time being .. the old functions will still exist.
All this would be a non-issue if php supported named parameters, which is essentially what we are reproducing using arrays.
Comment #10
Thomas Ilsche commentedI agree with moshe, and I think for day to day use the current forms api does a good job - however on complicated constructions i consider this to be really useful.
The problem i see is to keep the whole forms api consistent and easy to learn, any ideas?
I'd be against deprecating the current functions.
About the keyword definitions. I think it should be consistent with for hook_menu and all its "named parameter" friends, and to at least not confuse it more define the keywords without the leading underscore.
Comment #11
adrian commentedI'd prefer to make the menu system properties be consistent with the form system. actually.
I know the conventional logic is that all constants being uppercase, and the first versions of the form code did stick to that, but the end result
of the lowercase constants was far more readable code (the underscores however are a necessity to allow for nesting.)
What i was thinking was, that we could use the conventional form api as constructors for the form array.
ie:
turns into
instead of
and form_textfield turns into
Benefits :
1) easier to port
2) the ide thingy
Drawbacks :
1) more than one way to do something.
2) all forms will need to be upgraded, since the core form api will change. ie: breaks all of contrib.
3) Constructors could become unwieldy trying to tend to most of the parameters that can be set (weight, valid, validation_arguments, etc)
Comment #12
dries commentedThere should only be one way to build forms. Simplicity and uniformity is king. For now, I leave it up to Adrian to decide what this "one way" is going to look like. (I like his initial approach. The code is shorter which saves time too.)
Comment #13
chx commentedI second Dries. The old form API be gone. The IDE is going to be a problem, yes. A possible approach: the default array have all keys possible set to NULL or so.
Comment #14
Bèr Kessels commentedI prefer the One Way too. having more ways to do something normally results in two half-witted ways, instead of one way that works As Best As Possible.
I like the arrays approach. I love it, in fact. I have a feeling that the more code in drupal adopts the Array Way [tm], the more power AND uniformity we get. Just look at the success of array based menus: powerfull, yet simple to develop with.
But, I have a few hesitations: one is the lowercase CONSTANTS. I know, this is good for readability, so I lean towards the side of: then just use lowercase constants. But still, something does not feel right about it. I think this needs some more though, or comments of others.
Another thing I dislike is the way we use parameters to construct, IMO, completely different widgets. We should try to not think in terms of HTML, but in terms of usage and display. In HTML a collapsible form is similar -or nearly- to a noncollapsible. Same goes for a multi-select and none-multiselect select.
But where I really think we should have different APIs is for autofills. They are IMHO not textfields, but a complete separate widget. Thus they should get a separate API.
And last about the IDEs: allthough I do understand the problem, i beleive it is a very bad habit to let your code/application/product be limited, because of the tools you use. If your tools cannot handle libraries/snippets/etc beyond some function
calls, IMO you should get anoter IDE :). But surely we should not let us be held back by these limitations in these IDEs.
Comment #15
moshe weitzman commentedUm, snippits and macros are not a substitute for function complete. Snippits and macros are static entities which you manually create in the IDE and are then available as needed. If syntax changes for an given snippit, you have to manually change it. Thats just annoying enough to make you not use these feature at all. By contrast, function autocomplete just works the second you open a file. If you start working on a Contrib module you never seen before, the IDE introspects and is immediately ready for action. So all that nice PHPDoc that Adrian has written would be nicely used. Not so with snippits or macros.
If you guys want to see what the fuss about IDE is, download the free trial of Zend Studio (http://www.zend.com/store/products/zend-studio/) or Komodo (http://www.activestate.com/Products/Komodo/ - note the small link for the OSX alpha. I've tried the alpha and it works).
IDEs take a little while to get configured and get comfortable ... Create a project and start typing some common functions. See how the params show up and all our PHPDoc is there for your use. You can also quickly navigate your project via function names, and skip to the spot where a given function is defined. It is a tremendous time saver, and bug preventer. The IDEs above also offer a debugger which lets you step through your code and set breakpoints. Want to know the current value of a variable - just hover over it in your debugger. Once you've gotten the hang of this, you will never debug using print statements again.
I see nothing wrong with designing Drupal so that it uses those PHP language features that are friendly to IDEs. Namely, functions, classes, constants, etc. Arrays are very flexible, but that flexibility comes at a price.
Comment #16
chx commentedLike we have core.php for hooks we can have form.php for form API and let that help your hand with any IDE.
Here is an updated version of Adrian's patch. User login block reworked. I move on to other parts of user.module. I also created a theme_password() function, so I will post form.inc as well.
Comment #17
chx commentedComment #18
gordon commented+1 I like this patch a lot. but 2 things.
I think this will be great for theme developers and it will be easier to build forms for module developers.
Great job.
Comment #19
adrian commentedHere is an updated version of the patch.
1) admin / settings has been rewritten
2) Added form_radios and form_checkboxes and form_select and a few others
3) Very strict validation now .. the drupal_get_form function automatically validates any input .. no way to skip that. If it doesn't produce errors, it calls $form_id_execute(), or the optional $callback_execute().
4) Started the first part of the implementation of the multiple keyword, which is when an element can have multiple values. An example of this would be the 'files' element from upload.module , where more files get added, and also the primary / secondary links configuration of phptemplate.
Still needs to be done : The clean_url validation, and any other module with a _settings hook. I haven't integrated chx' user module work at this point.
Comment #20
adrian commentedHere's the patch.
I'm also still busy with the filter format, which has unique requirements and needs to be a filter_format element type (gets rid of the in-line html)
Comment #21
Dave Cohen commentedOne thing I like about the current API is that you can inject arbitrary HTML in the middle of a form if you see fit. It's not obvious to me how to do that with the new API. Is there a way?
Could I, for example, arrange my form fields in a table with two or three columns?
Comment #22
naudefj commentedI would also like to be able to display forms in HTML tables. Here's a great article explaining how forms can be styled using tables - http://www.cs.tut.fi/~jkorpela/forms/tables.html
Comment #23
adrian commentedEVERY form will now have a theme function, as every form now has it's own (unique) form-id.
You can create a theme_my_form_id() function if you are a developer, and require the form to be differently layed out (like for instance, adding all the element outputs to a table).
You can create a mytheme_my_form_id() if you are a theme developer, that can override the form layout. (as is shown by the current node_form)
[?
function theme_node_form($form) {
$output .= '
$output .= '
$output .= '
$output .= form_render($form['author']);
$output .= '
';
$output .= '
$output .= form_render($form['options']);
$output .= '
';
$output .= '
';
$output .= '
$output .= form_render($form_render);
$output .= '
';
$output .= '
';
return $output;
}
?]
You can create a phptemplate stub to load it from a template.
and the current node_form template being :
[?
print form_render($form['author'])print form_render($form['options'])print form_render($form)?]
NOTE: As a developer, you can even remix forms you didn't design. Infact, it gives you complete themeability over everything.
Comment #24
adrian commentedI hate the php filter ..
here's the theme_ function ..
i don't have time to escape the template right
I am attaching my presentation from drupalcon in portland.It has all the examples, although stuff like the validation has changed slightly.
Comment #25
adrian commentedCall for help :
Code freeze for Drupal 4.7 is coming very quickly , and a lot of work is still needed to get this functionality in before the code freeze happens.
As this patch is incredibly important (even if only considered from a security point of view), we need people to help us port all the forms in
Drupal at the moment.
If anyone is interested in helping, could you please contact me, so we can coordinate.
Comment #26
killes@www.drop.org commentedYou can assign me a module to conver as soon as my revisions patch is in core. I think I'd like to convert profile.module.
Comment #27
Dave Cohen commentedRegarding #24:
Now I see why you keep the [printed] flag during node_render.
Should this line:
$output .= form_render($form_render);read:
$output .= form_render($form);??? (That is, I don't see where variable $form_render is coming from).
Regarding #25:
Must every form be converted in order to include this? Drupal 4.7 will still support the old forms API, yes?
I see that this was discussed early in the thread. For those of us with custom modules life would be a lot easier if the old form api sticks around until say a 5.0 release.
Comment #28
killes@www.drop.org commented@yogadex: To those of us who roll out the actual security releases till 4am in the morning the disappearance of the old api with 4.7 will provide a lot more sleep. We win, backwards compatibility sucks.
Comment #29
adrian commentedThe old form api will remain in core for a maximum of one release.
another 6-9 months to convert your modules is more than enough time... plus most of the new uber features (cck etc) are going to require you to upgrade to the new system.
Meanwhile, new functionality like the install wizards are going to require you to use this form api.
Comment #30
adrian commentedAnd regarding the form_render question .. it's not a variable, it's a small recursive function.
the theme function is passed the entire form tree. The designer can choose to remix the form however he chooses. Since elements are nested, and for instance the fieldsets, are named .. you can use form_render($form['elementname']) , which will print that element, and set the printed flag so it won't be printed again.
Like in the example where the author and options fieldsets are seperated out from the form and displayed seperately. form_render($form) in turn will print anything that hasn't been printed yet.
if you wanted to seperate out the author field on the page, you could use form_render($form['author']['name']) , and it would print that element wherever, and when you then called form_render($form['author']) or form_render($form); , it would not be printed again.
Comment #31
Dave Cohen commented@killes: I certainly don't want you losing sleep ;) I'm glad to hear the new and old will coexist for at least one release. (Unless there's a security issue - that's another story)
@adrian: I understand the form_render() function and it's nifty. But there is a typo in both your attached presentation and #24 above, where "$form_render" is written and it should be "$form", if I am reading correctly. Thanks for explaining.
Comment #32
chx commentedI merged and rerolled against current HEAD.
Comment #33
m3avrck commentedMinor include bug in the node.module patch:
that
include_onceis missing the'./'part.Comment #34
ax commentedthat second
shouldn't be changed but *removed*, because it is a duplicate of 8 lines above.
Comment #35
m3avrck commentedah yes, an even better catch than mine, touche!
Comment #36
chx commentedNot so. The first should be removed 'cos it is hard to patch against the cvs id :)
Comment #37
ax commentedallright, ok, of course, the first one.
what would be even better would be a working patch. the ones attached (last one and before) don't include form.inc, generate some duplicate functions that result in "PHP Fatal errors: Cannot redeclare functions()" (system_elements(), theme_node_form()), and "PHP Warning: Call-time pass-by-reference has been deprecated - argument passed by value"s. chx: are you working on this?
i would much like to help testing the new forms api and getting it into 4.7 because thats exactly what i need for a bigger project at work where we are considering using Drupal as base framework. the one showstopper is the extensability of Drupal forms ...
thanks for all the work done up to now, anyway.
Comment #38
jvandyk commentedHere's an updated patch against HEAD that is mostly working. Karoly provided the updated node.module. For me, there seems to be an issue in form.inc in the recursive _form_builder() function where it is recursing even when $element is not an array but is a scalar.
Comment #39
m3avrck commentedNot to nitpick, but in node.module, the patch has
+include_once 'includes/form.inc';but should read+include_once './includes/form.inc';for consistency and performance :)Comment #40
webchickI don't know if this is just the Drupal newbie in me talking, but I am getting quite a few errors with this patch (Drupal HEAD, up-to-date as of about 5 minutes ago). I've uploaded the form.inc from #19 and applied the forms_2.patch from #38, and I'm getting errors like the following:
admin/settings:
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 511.
admin/comment/configure, admin/settings/user:
warning: Missing argument 2 for system_settings_form() in $DRUPAL_ROOT/modules/system.module on line 733.
node/add/[anything]:
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 406.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 403.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 411.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 406.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 403.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 411.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 406.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 403.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 411.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 406.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 403.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 411.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 406.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 403.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 411.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 435.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 448.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 435.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 448.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 435.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 448.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 435.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 448.
warning: Invalid argument supplied for foreach() in $DRUPAL_ROOT/includes/form.inc on line 435.
warning: Cannot use a scalar value as an array in $DRUPAL_ROOT/includes/form.inc on line 448.
---
Any ideas?
Comment #41
jvandyk commentedThat's why I said "mostly working." :)
m3avrck, sorry, I diffed against the copy where I hadn't corrected the ./ thing.
Comment #42
adrian commentedGood morning guys.
I am looking at those errors now, and i will upload an updated forms.inc in a short while.
Comment #43
adrian commentedHere is an updated patch and includes/form.inc.
Changes :
1 ) Introduce a global $form_variables array, which works exactly like $_POST['edit'] used to, except the values in it are filtered through the form system and only values that have form elements will be in it. Each form being processed on a page resets this array, so they won't interfere with each other.
2) introduce a form_id hidden that gets submitted with the page. This means it can intelligently decide which form to process.
3) Fix the bug above. I wrapped the offending lines in if is_array() , HOWEVER .. at the point I call that code I am fairly certain I am only working on arrays, hence I need to look it over more
4) fixed the user login form on /user. The user login block still doesn't work
5) Added a default css class (and some temporary css in drupal.css) for everything rendered with the form api. All other forms will have a thick red border if they have not been ported.
6) fixed a bug with element_info where it was setting the wrong defaults and then messing up the first form element because of it.
7) finished the filter module 'filter_format' element. Filter forms are printing now.
8) Added the 'weight' element. Could be cool to theme this with something ajaxy, right ?
9) Fixed some bugs with admin/system
10) Updated the following modules : Book, Page, Story, Blog, Node, Taxonomy and a fixed user form.
11) Moved the inclusion of form.inc to it's rightful place in drupal_bootstrap_full.
12) Added a bunch of comments to places. We will still have to go through all the comments and make sure they all 'parse' =)
The node form is not actually working or validated at present, and if someone could take a look at that , I'd be much obliged. It's important to get used to the new (strict) workflow for forms. It generally means having to shift some code around, and it makes it harder to write 'bad code'.
Comment #44
adrian commentedhere's the patch
Comment #45
dries commentedintroduce a form_id hidden that gets submitted with the page. This means it can intelligently decide which form to process.
Does this mean people could change the ID before they submit the form? I'm not sure that is a good idea.
Comment #46
adrian commentedThe access check is tied to the page, not to the form.
If the page has 2 forms on the page, this check is to see which of the two he submitted.
Changing the form_id in the hidden will do nothing but cause the form not to execute, at all.
Comment #47
m3avrck commentedRunning this patch I'm getting this error
Fatal error: _drupal_bootstrap_full() [function.require]: Failed opening required './includes/form.inc'Didn't see the file anywhere in the patch, unless I missed something...
Comment #48
adrian commenteddrupal.org renames the files to avoid conflicts.
it's attached as form_2.inc
Comment #49
asimmonds commentedShould there be "return_value" and "delta" property constants defined in form.inc?
Comment #50
adrian commentedWell spotted.
Added those defines.
Comment #51
nicopepe commentedHello
I am a newsbe and i am vey concern about the form project. I want first to congratulaed for all this nice work. I propose this code in the attached file. Tell me what you think, and i'll finished it.
Comment #52
nicopepe commentedHello again,
I see no reaction to my proposition. Maybe not interresting code ? My aim with that code is :
- Open all the possibilities of attribute in an input balise.
- Not multiply the number of constant (The key of an element is an attribute name, define by the programmer)
- Check within drupal_attributes function if these attributes are correct in an INPUT Balise.
- Include a javascript code insertion for form client validation.
In fact i would like to create later on, a module with generic javascript for client validation (Date checking, required fields, ...). I have this in mind when i proposed this code.
Any answer this time ?
Comment #53
ezheidtmann commentednicopepe, it is difficult to tell what your changes are because you have not submitted a patch. Take a look at http://drupal.org/patch. Your code might get a better response that way.
Comment #54
dries commentedAs an aside, it might be worth looking into the XForms. They have a short introduction for HTML authors in case you don't feel like reading the entire specification. A friend of mine is a member of the XForms working group and told me someone was working on a JavaScript implementation of XForms.
More importantly, XForms have (client-side) validation build-in. For example, to specify a valid range you use:
<range ref="volume" start="1" end="10" step="0.5"/>Similarly, XForms have the ability to state that a value must be supplied before the form is submitted, have a notion of typed values (eg. you can specify that you expect an URL, integer or date to be entered). XForms also include stuff to introduce wizard-like behavior of filling in a form in stages, include functionality to dynamically add fields (eg. like when you run out of textfields for poll questions), etc. A lot of the stuff we have been talking about. :-)
It might be useful to check if our developer API would map gracefully on XForms. It would impose that we are XForms-ready (future proof). It's especially interesting because Mozilla is working on a XForms implementation. (XForms 1.0 support will be included in Firefox 1.1. You can test it using the nightly Firefox builds.)
Comment #55
nicopepe commentedAs a newsbe, i have not install any patch module Yet. So i will do it.
For Dries, i will have a look on this Xforms projet, but i just wonder if it is MS compatible (80% of market) ?
Maybe before adding this code I should have write my ideas. I think this new form API should consider having an easy way to perform database update as well as new records adding. So in my view, 2 specials “events” are needed :
- call an user defined procedure BEFORE the Form is Loaded (non existing yet ?) to read database and set value to the form.
- call an user defined procedure AFTER the Form is validate (drupal_execute_form)to write to the database update or new record.
I agree with Adrian to use arrays. They allowed flexibility. I think using $form and $element arrays with others keys than theses defined with property constants is a good way. Property constants are used for regular Drupal core functionality, and user defined keys values used for extra functionalities. This means that the $form array should have a well documented structure to be able to extend it.
I see here three examples:
- Use all JS events (as my code suggest) for client validation. examples :
$form['onSubmit'] = "js function name or code...";
$element['onkeydown'] = "js function name or code...";
- Create an $element[‘NonValidationMessage’] Key used in drupal_validate_form user function to return to the user when the validation of an element is not OK (This message could also be used in JS in client validation).
- Possibility for a programmer to input in the $element array the name of the database field and database table to store the input value in case of correct validation. Exemple :
$form['tablename'] = "mytable";
$form['idValue'] = "value";
$form['idName'] = "myid";
$element['Databasefieldname'] = "myfieldname";
Then create an function to create automatic SELECT STATMENT to read the value before display the form ( When we need to modify value stored in a database) or INPUT SQL statement after validation,
I hope i am clear with my ideas. Maybe some of them could be used already in the core.
Comment #56
dries commentednicopepe: I'm not saying we should implement XForms at this point. I meant to say that (i) XForms looks like an emerging standard and that (ii) the XForms API tries to solve the same problems we are trying to solve with the new form API. It is worth investigating XForms. Being able to generate XForms-compliant code with minimal changes is a nice extra, but certainly not a must at this point. Hope that clarifies my comment.
Comment #57
junyor commentedDries: It'd probably be more interesting to look at Web Forms 2: http://www.whatwg.org/specs/web-forms/current-work/. It's geared toward the Web, whereas XForms isn't. Web Forms 2 is also more likely to see native implementations.
Comment #58
killes@www.drop.org commentedDries: In my book we are trying to solve a securoty issue woth this patch: the case of inserting bogus fields into our html forms. Client side validation is noce from a usability pov but we are trying to do server side.
Comment #59
dries commentedGerhard: it's obvious that client-side validation is no replacement for server-side validation. :-)
Anyway, instead of looking years ahead, let's focus on the patch at hand.
Comment #60
nicopepe commentedClient side validation will never replace server side validation for security reason !
I do understand that client side is not yet a priority, but please let doors open for module developper if they want to implement Client side validation in their module.
Comment #61
adrian commentedHere is an updated, and more complete version of this patch.
I had a bit of a SNAFU with the multiples code, and needed to refactor it to work properly.
Changes in this version :
1) Introduced a 'process' property. This is used by the radios and checkboxes elements, to call 'expand_radios' and 'expand_checkboxes' functions which turn the single element into a set of elements.
2) admin/themes screen done.
3) deprecated fix_checkboxes, since it was no longer needed. Checkboxes and radios work perfectly now ( they were broken previously).
4) The way to access the form value is through a global $form_values array, that is set up to the structure of the form. It's no longer flattened, and it works perfectly.
5) Introduced an array_walk_recursive function (copied from PHPCompat in PEAR) that allows you to step through the values and do something with each key. (admin/settings uses this property).
6) Moved the old form api into a legacy.inc
7) Did a bunch more forms.
In this tarball you will find the 2 new files (legacy.inc and form.inc) and the current patch.
Comment #62
adrian commentedHere's the status document of all the forms (rtf export from omnioutliner)
It's incomplete, as I haven't finished cataloging all the forms yet.
Comment #63
m3avrck commentedNo patch in that zip :)
Comment #64
m3avrck commentedAlso, adrian, is there a way to add events or set variables in javascript, if the submit button on a form has been clicked? Need this functionality for a patch about to (hopefully!) make its way into HEAD soon.
Comment #65
adrian commentedI'm sure it's possible, but I think we prefer attaching events and the like onto forms using the id attribute.
here's the patch file.
Comment #66
adrian commentedHere's a complete list of the forms in drupal that still need changing.
Everything that has already been done is not on this list (ie: all the node modules, and the like)
Some of the forms mix normal output, and form output in the same page, and switch out depending on certain requirments (the aggregator_list_page was an example of this), making it a fairly intensive process to seperate the two pieces of functionality into clean code.
If something is rated simple, it means it only involves changing the functions to arrays, and either returning the array, or returning the final form using drupal_get_form('form_id', $form);
If we want any chance of getting this into core before 4.7, I am going to need some volunteers to handle tackling these forms for me. Once again, I am looking for a few good men (where men == female OR men == male .. obviously. =) ).
I am going to be concentrating on the really complex forms, and the theme('confirm') form, which is required by a fair amount of things.
Comment #67
jeremy commentedI thought I'd give this patch a quick try, but ran into a couple problems. First is very minor, it makes some changes to settings.php that it shouldn't -- something to clean up before the final version.
Second, it adds includes for form.inc and legacy.inc, but the files themselves are not actually included in the patch.
Comment #68
adrian commentedThey are in the tarball i uploaded earlier.
Comment #69
jeremy commentedI tried that last night too, but the earlier tarball was 0 bytes and contained no files:
Attachment: forms.tar.bz2 (0 bytes)Comment #70
adrian commentedThat is the weirdest thing ..
locally :
Benton:~/dev/forms adrian$ ls -l forms.tar.bz2
-rw-r--r-- 1 adrian adrian 28489 Sep 12 15:30 forms.tar.bz2
Comment #71
adrian commentedHtml version of the status list.
Comment #72
dries commentedGuys, please take a look at the status page. If we want the new form API in Drupal 4.7, we'll have to work together pretty much non-stop to complete it! Care to help? Pick an item, migrate to the new form API and upload a patch.
Comment #73
Bèr Kessels commentedCan we not exclude this from the code freeze? I mean that we now (last days) focus on all these outstanding patches for 4.7. and then have acollaborative effort on this forms patch. That will at least give us the benefit that we can aim on a stable target. Instead of junting on a still changing core. From what I see a lot of people are focussing very hard at their babies in the queue, to try to push them into 4.7 (that counts for me anyway) So they will not spend any time on the form api yet.
Comment #74
webchickFor what it's worth, I agree with Bèr. I've been picking away at comment.module to make it compatible with the forms API, but it's very difficult since the patch needed to enact all these changes differs from day to day (today I applied the .tar'ed version and still am getting errors with a few hunks which I need to troubleshoot first in order to make sure my changes aren't causing errors).
Once things are more "settled" with the rest of core, it seems like it would be much easier to make a more "stable" patch as a starting point, which would thus ease efforts on the part of the rest of us to get the changes made. This patch represents a HUGE change, and I worry about the idea of trying cramming it in at the last minute.
Comment #75
Souvent22 commentedI totally agree with the above comments. With so many chagnes happening so fast, we wake up to a new core each morning, and must make changes accordingly. I don't know what the core will get 'stable' enough before the freeze to really hack through what needs to be done in an efficient manner. We all seem to agree this needs to happen, but perhaps a better plan of 'how' it should happen since it is such a big change would make things easier, more stable, and not make it seem like we're trying to cram a square block through a round hole.
Comment #76
m3avrck commentedI agree with Ber and Souvent. I think we should all focus on our pet patches for the Drupal 4.7 freeze (which I think should be Friday give us that one day ;). After that, we should have a "sub-freeze" where *only* FORM related API patches go in, set this for 3-4 days after the 4.7 freeze. Then, once that is complete, *then* get back into the regular bug/performance/usability freeze over all.
Comment #77
dries commentedLet's do it the other way around. If you help with the form API, you get a 3-day extension for your other patches. The form API is far more important than so it needs to hit core first. I already granted a 2 week extension, and unless this is near completion, I won't extend the current development cycle. Sorry.
Comment #78
chx commentedDries, we have a deal. Contacted Adrian, will start working on filter module 90 minutes from now.
Comment #79
dries commentedI volunteer to tackle the statistics.module as a starter.
Comment #80
matt westgate commentedPut a mark next to my name for path module.
Comment #81
adrian commentedI am tackling the system module, and (god forbid) node_admin_node (which is the single most complex form i have come accross).
I am desperately looking for someone who uses localization to help port locale.module and locale.inc
Comment #82
Bèr Kessels commentedquick rerolled system module patch.
which rasies the question: how to we work on this? send in patches per file, i assume?
Comment #83
Bèr Kessels commentedmy hand goes up for blog.module. to get warmed up.
Comment #84
Tobias Maier commentedi want to start with watchdog as my first.
Comment #85
Bèr Kessels commentedhmm; make that block.module. my mistake. I am on bloCK.module now.
Comment #86
m3avrck commentedhold on the filter.module ... really nice patch about to make it's way in to redo that area: http://drupal.org/node/27364 ... talked to Dries, he said he'll commit this filter patch before the FORMs API rewrite team swoops in so we don't waste our times doubling coding effort :)
Comment #87
adrian commentedquick update of the patch.
Also, the filter module is not being worked on right now, as we are going to be redoing most of it before we port it.
Comment #88
Tobias Maier commentedhello,
I know I'm doing the simplest form of all - the watchdog.module
but i'm running in some errors.
I hope you can help me
here are the important code snipets which are bugging me:
the value of $_SESSION['watchdog_overview_filter'] and $form_values['filter'] remain 'all' the whole time...
why?
I tried a lot.
I found out, that "..._execute" will run when drupal_get_form is called.
So all places where $_SESSION['watchdog_overview_filter'] were called before wont get the current value...
Interesting is
<select name="edit[edit[filter]]" id="edit-filter"><option value="all" selected="selected">all messages</option><opt..., toois this edit[edit[filter]] really wanted?
I dont know how to solve this...
please give me some hints.
Thanks
the attached patch is not working at the moment!!
Comment #89
Bèr Kessels commentedI give up on block.module. I have been up and coding for nearly 48 hours now, it is just too much. I am even thinking in arrays ATM :) array('bed' => array('top'=>'sheets')) and so on :)
So , release the 'lock' on block.module, hereby.
Comment #90
Tobias Maier commentedI have to give up for today too.
Maybe I have time again tomorrow afternoon
cya
Comment #91
adrian commentedTobias : Thank you kindly, I have integrated your code, and you found a bug in the select element, and a 1 line fix later .. it was working.
It's been integrated. Thanks.
Attached is the latest patch , which also includes the new version of the theme('confirm') dialog, which has been rewritten and called confirm_form()
An example for porting any of the confirm screens :
Turns into :
I changed the parameter order to be inline with the rest of the form system, ie: a form_id, and then a $form array (which has the same use
as the $extra parameter had before).
To have something happen, just create a $form_id_execute($form_id, $form) function, provided it passes the validation.
The function has also been moved to system.module (since it has nothing to do with themes anymore).
Comment #92
adrian commentedAttached is an updated document with what the progress is.
Comment #93
chx commentedform.inc , theme_select has an extra
edit[ ...]Comment #94
chx commentedstory (and maybe others) has
$form['taxonomy'] = taxonomy_node_form('blog', $node);Comment #95
chx commentedLast update from me this night.
function system_elements()has two checkbox definition and I like the first one better.Comment #96
chx commentedComment #97
adrian commentedThe taxonomy_node_form has been changed to return a $form array.
Here's an updated patch, including the forum module patch from Chx .. thanks man.
Dries has started working on the user module.
Comment #98
adrian commentedand the file *blush*
Comment #99
Tobias Maier commentedI applied the last patch on my drupal HEAD.
The watchdog.module does not work as expected :(
the html-output is
<select name="edit[edit[filter]]" id="edit-filter"><option value="all" selected="selected">all m...again...Comment #100
Tobias Maier commentedanother error:
for example on /node/add/page
the label for-value has to be the same as the input id-value (see http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.9.1)
this error is on every form...
Comment #101
dries commentedConverted the access rules checks form. Patch for user.module attached.
Comment #102
webchickHere should be book.module for the most part, with the exception of the admin link function which I've tagged as TODO after talking with adrian. I swapped my comment.module assignment with eaton and took this one instead.
Comment #103
dries commentedUpdated two more forms in user.module. Discard #101 and use this one instead. Could you double-check the use of default_value in _user_admin_access_form(). Would that be correct?
Comment #104
chx commentedHere are the menu forms. I even tested it somewhat :)
Comment #105
chx commentedMaybe others also have some hard time to figure out how to put form elements into a table.
You construct the form, with non-interactive elements ie. plain text going in as
array(type => 'markup', value => ...). Then you write the appropriate theme function and callform_renderin a loop. If you useforeach ($form as $key => $element) {for this loop be aware that you need to pass$form[$key][..]to form_render so that it can set that form element to rendered. Or you canunset($form[$key]);at the end of the row. All this is necessary because the usual ending is:<?
$output = theme('table', $header, $rows);
$output .= form_render($form);
return $output;
?>
Where this
form_rendercall adds buttons and everything else not yet rendered.Comment #106
chx commentedEek! Let's try again:
because the usual ending is:
Where this
form_rendercall adds buttons and everything else not yet rendered.Comment #107
chx commentedLook into system.module and (soon) filter.module for examples on how to do this table render dance.
Comment #108
eaton commentedNot as good as the 'finished product' but here's the very-close-to-finished patched version of comment.module.*
Currently broken:
I'm looking into these issues; if anyone wants to take a stab at them, it'd certainly be cool.
Currently working:
*As I discussed on #drupal, the formapi work I'm doing is based on the already-completed comment module patch at http://drupal.org/node/28255 ... it removes moderation for implementation in a separate module, and adds a set of nodeapi style hooks for comment enhancements (file uploading, captchas, etc).
Comment #109
eaton commentedSomething I just realized a few minutes ago that tripped me up...
Forms with nested groups of elements have to be navigated as keyed arrays: $form['admin']['options'] for example. When a newly loaded object is prep'd for use using object2array($object), it flattens the properties to $form['options'] and so on. if you're not expecting it, it can cause all sorts of wackiness.
It'd be great if the API could account for this *somehow* -- as of right now it means that preview/validate code may have to do double-duty whenever an object is being edited, rather than created.
(then again, I could just be tired...)
Comment #110
hunmonk commenteddries' latest patch had a failed hunk in modules/blog.module--i'm assuming that was because of a recently applied patch/adjustment. attached is a new patch that corrects this.
Comment #111
hunmonk commentedoops. ignore that patch i posted in #110--i wasn't clear on how we were tackling this.
Comment #112
eaton commentedUltra mega super patch. this one takes adrian's most recent patch and rolls in all the changes posted SINCE then. (including chx' menu.module, webchick's book.module, thehunmonkgroup's blog.module fix, and my comment.module changes)
Comment #113
eaton commenteder... AND dries' patch, too.
Comment #114
adrian commentedHere's my updated forms.inc file.
apparently i didn't post the select box fix.
Comment #115
adrian commentedno wait.
HERE's my form.inc
=)
Comment #116
eaton commentedHere's the latest copy of comments.module. the only thing not working at present is the stuff managed by the form_settings hook. Other than that, things seem to be flying.
Comment #117
adrian commentedlatest status document.
If you see anything here incorrect, please get a hold of me on irc.
Comment #118
adrian commentedsigh.
Comment #119
adrian commentedok.
this sending of patches is silly.
i'm going to set up svn accounts on dev.bryght.com for anyone interested in helping. Contact me on irc if you want to help.
Comment #120
adrian commentedWiki Page
http://dev.bryght.com/t/wiki/DrupalFormsApi
It has a publicly editable status document.
If you work on something, please mark and keep track of what's done.
If there's any documentation/tips you want to share, please put it there too..
The current source is on http://dev.bryght.com/t/browser/forms/
Comment #121
junyor commentedAdrian's still asleep, so here's a patch for update.php.
Comment #122
junyor commentedHere's throttle.module.
Comment #123
gordon commentedDue to the dropping of the hook_textarea() I have been looking at other ways that a WYSIWYG Editor can be hooked into drupal, but also maybe even a better method.
The idea that I have come up with is creating a new hook that is called from form_render() called hook_form_render(&$form) which will allow contributed modules to change the $form array before the html is generated.
This doesn't allow me to add any html to the form, but for adding a WYSIWYG editor like Xinha I do not have to.
What I can do which will be very clean is add to the selected textareas is add to the attributes something like 'editor' => 'xinha' and the do a drupal_add_js() to load Xinha, which will search all the textareas in the page which the attribute editor with a value of xinha. The means that I will be adding no js to the rendered page, just 1 include and an attribute.
I started looking at this but the problem is that form_render is a recusive command. I have an idea that I can get around it by changing the function to
function form_render(&$form, $root = true) {
}
and then doing the recusive call with false.
I beleive this would give extremely amount of control over forms from contributed modules.
Comment #124
hunmonk commentedwe submitted a little quick reference guide for the new form API here. Just a start, but quite handy!
Comment #125
gordon commentedI have been working on my idea to create a new hook called form_render() which is called during drupal_get_form().
This is such a powerful hook, as it means that the entire form can be edited before it is displayed. You can change fields, add fields, delete fields without any problems. This makes the nodeapi form pre and form post more of less obsolete. You can do more here and it is available to all forms.
How does this replace hook_textarea()? In most cases people do not return any additional html, they just remember the textarea and then do some processing at the bottom, such as the case with htmlarea. With the new js stuff and the better method of implementing js is there is no js on the actual page. The elements are flagged and then the included js then searches for the relevant elements and then does what they need to.
So in the case of htmlarea I would add editor="xinha" to each required textarea and then search for that to display the page. Much much more elegant than the existing method.
Other use cases would be the event module. The date is quite ugly, I prefer to use The coolest DHTML/js calendar. S what I can do is create my own date time field and then in the hook_form_render() I can just rewrite the original date field created by the event module with my own one.
We need something like this for the WYSIWYG editors in contribution so they can attach to the textareas, and this will create a very clean method of doing this.
Comment #126
gordon commentedAlso here is a small example module that adds "blah" to all the titles in the form. Just an example of ehat can be done.
Comment #127
adrian commentedRegarding the form_render hook, I am going to -1 that.
i would prefer to do the hook in a different way.
ie: pass the entire form array to a hook, and allow you to alter it in any way you want.
This would allow you to step through all the elements, if you so wish, but would also allow you to alter the form using the form id.
ie: in form_id = event_node_form override the weight of the title field to 100 to let it display at the bottom of the form.
And I also think there has to be a better way to do the htmlarea functionality.
Comment #128
adrian commentedhah!
seems like we had the same idea after all.
Perhaps we should call the hook form_alter or something, since you aren't actually affecting the html output, but the form data structure.
The other thing i want to do is enable you to specify 'interface levels' for each of the elements, meaning you can set the taxonomy to not display for certain groups of users, or possibly default the taxonomy selection/title based on certain requirements.
I am against changing form_render to have the root parameter though, as I don't believe it's neccesary.
Comment #129
gordon commentedAfter I implemented the change into the form_render function I found that it was being call multiple times. I did not want this. I only wanted the the hook to be called once.
I then moved the hook into the drupal_get_form() where all modules should call the formsapi. I think it would be rare and this should not matter too much.
I have renamed the hook form_alter as per your request. I am not linked to the name, I more want the functionality.
Because the hook is not being called from the form_render() there is no need for the $root to protect the recusion.
Comment #130
adrian commentedI've added the form_alter hook to my form.inc
will commit it soon.
Comment #131
hunmonk commentedok, i've done an exhaustive search of all modules and .inc files, looking for all forms that still need to be converted. found some that weren't in adrian's initial list. we're in decent shape, but there's still more work to do! you can see the updated list here, and pick out the task of your choice... :)
Comment #132
m3avrck commentedWhat's the status? It seems like most forms are almost all done? Is this still going in? Really need this for a new module working on let me know what I can do! Thanks!
Comment #133
hunmonk commentedthe forms upgrade is nearly complete. all forms have been converted, and at least 90% of the basic testing/debugging is done.
plan of action from here on out:
Comment #134
adrian commentedLadies and gentlemen.
I present to you, the single largest patch ever contributed to Drupal.
In fact, it's a partial rewrite of the entire input layer of Drupal, with a final patch file that is a shocking 411K in size.
This project has been a testiment to what we can achieve as a community, and has also taught us a lot about coordination and
managing a project of this magnitude. I think we've proven to ourself that no task is too big, if we work together.
I would like to thank Chx, Chad (thehunmonkgroup), Dries, Killes, Webchick, Asimmonds, Junyor, Eaton and Gordon for their contributions,
without which this patch would not have been possible. Really guys, you should be proud of yourselves =)
The next big task is documenting it all. But, we do now have a large group of people who are comfortable with the
new API, so it shouldn't be too painful a task.
Comment #135
adrian commentedHere is the the form.inc required for the patch. Place in includes/
Comment #136
adrian commentedIncluded is the legacy.inc file containing the current form functions.
I would also like to apologize to Tobias for neglecting to thank him in my previous post. It was purely due to my lack of proofreading =).
Comment #137
adrian commentedAnd here's it all in a tarball.
Comment #138
m3avrck commentedI just want to say you guys have done an awesome job with this patch, and for Adrian for coordinating this massive patch :-)
I wish I had more free time earlier to help convert forms but alas, I was swamped with work :-/ But don't worry, I do plan to help test this extensively as I'm working on 2 drupal HEAD sites currently so you can be sure I'll be submitting a many bug reports and hopefully patches too, if I can figure out what's up.
Again, awesome work guys. Dries, let's get this committed so we can start testing this ASAP!!! Cheers!
Comment #139
Steven commentedI was going to commit this after a bunch of requests on #drupal, but I don't understand why it was marked ready to be committed as there are severe bugs that break Drupal's most basic features.
- Node previewing doesn't seem to work? Fields disappear and errors appear.
- Logging in from the sidebar block is impossible? That form also has two <form> tags, one inside the other.
- upload.module was horribly broken even without Javascript. The JS-part was completely ignored in the conversion: wrappers were not wrapping anything, marker input-hidden's were not marking anything anymore.
- The implementation of prefix/suffix is odd to say the least. The documentation says it is only used for 'markup' type form elements, yet it is used in a couple of places on other elements too (textfield, hidden, fieldset). But textfield never outputs the prefix or suffix. It seems logical for every theme_element() to start with the prefix and end with the suffix. Implementing it in only some cases (as is done now) is odd. Why not move them into form_render() itself? Keeping them in theme_element() is wasteful, and doesn't give you any benefit in themability as they are solid chunks of HTML anyway (which are required for styling or ajax in several cases).
I started doing code clean up and fixing JS upload, but the buggyness prevents me from getting anything done.
Comment #140
chx commentedI apologize -- the version I had was really working. There were some last-time changes and those broke this and that. I can't svn up currently and have no clue how could I proceed. I defnitely do not want to reroll a 400K patch. A form.inc is attached however which fixes a lot of problems.
In user.module, the following fixes an infite loop if the wrong password is entered:
Comment #141
chx commentedah yes -- node preview and submit is broken badly. I _know_ they were working for me but not now and I do not have any more time to spend on this -- I spent already too much *sigh*.
Comment #142
adrian commentedOk. i've almost fixed node_preview.
I moved it so that the preview is an element added to the form, meaning you can move it around in the display (ie: put it at the bottom if that's what suits you).
I'll be testing the fixed form_upload a bit , and i've already done the prefix / suffix move to form_render. Thanks for that.
Comment #143
adrian commentedNew version of the patch.
Fixed the node preview thing and the file upload.
Comment #144
adrian commentedstatus ...
Comment #145
dries commentedApplying the patch results in a parse error: the problem lies within the contact.module.
Comment #146
dries commentedPatch committed, setting to active! =)
Comment #147
asimmonds commentedAttached is a patch to update contact.module
Comment #148
dries commentedCommitted.
Let's mark this fixed when the documentation is in place.
Comment #149
Tobias Maier commentedand here comes a patch which fixes watchdog
Comment #150
Tobias Maier commentedwhat I fixed:
if you filtered for a message type you had to reload the page again to see any effect
Comment #151
Tobias Maier commentedanother error: the Theme configuration on the user/edit page is broken for me
errors on /admin/themes and /admin/block after changing the theme all the blocks where hidden
SQL error messages on /admin/block
"chameleon settings" is available on /admin/block but this theme is disabled
this errors are here for me since the last update
Comment #152
Tobias Maier commentedsorry the only thing broken through the patch is the look of the Theme configuration on /user/1/edit
it seems like that if you select a theme for the first time from the /user/*/edit page all the blocks are not available.
-->also there is way missing to set it back to the default value
Comment #153
Tobias Maier commentedI tried to fix the "Theme configuration"-problem but it was too advanced for me.
could please the same person who did the system_themes() look at system_user()
I found out that it is possible to assign a theme just to a part of a $form-array.
you could maybe use
$form['themes'][theme] = 'system_user_themes';and create the function theme_system_user_themes()
I tried it since my last post but had problems to understand what happens at systme_themes() (its very similar to the other function)
Comment #154
hunmonk commentedjust a heads up that i've been commissioned by Kieran to write doc for the forms api. it's a top priority for me, and my goal is to have a good first effort submitted by sunday evening. i'll be working w/ Adrian, the other folks who contributed heavily to the upgrade, and the docs team to accomplish this task.
Comment #155
kbahey commentedAny changes done in admin/settings are not saved after the patch hit HEAD.
Details here http://drupal.org/node/33347
Comment #156
hunmonk commentedsepeck has been kind enough to create a nice workspace for the evolving forms API documentation:
http://scratch.blkmtn.org/
there you can read the bleeding edge of forms API doc, which is currently an outline roadmap for full documentation, and a quickstart guide.
if you find anything that needs to be changed, please register at that site and create a new book page detailing the change, or add a new comment to an already existing book page, and i'll work it into the doc. i prefer this method instead of people bombing me with emails and pm's... :)
Comment #157
ax commenteddid anyone actually performance-test this big change?
Comment #158
killes@www.drop.org commentedax; not to my knowledge. But it hardly matters as forms are not found on every page.
Comment #159
ezheidtmann commentedkilles, with the login block enabled, a form is on every page (at least for anonymous users).
Comment #160
deekayen commentedI'm guessing this is the right issue to say the primary/secondary links don't update when I submit changes on /admin/themes/settings.
Comment #161
m3avrck commentedAlso I think I found another bug as well. I have two forms on the same page both of which should be submitted seperately. One form has required fields but if I submit the other form, the first one always popups saying "required field" missing. Any ideas?
Comment #162
chx commentedThis thread is way too long. Please do not post to it any more but use new issues.