this thread will be for clarification/discussion of what is (or should be) covered by this API

Comments

arhak’s picture

The purpose of Driven API is to provide a generic mechanism to work with form elements (FAPI) in such way that other modules don't have to repeat/duplicate code and effort.
FAPI provides a standard mechanism to describe how forms behave, therefore each element can be handled/altered in a generic way having a minimal info regarding its nature. There are some elements which are very basic, and others that work in conjunction to achieve an indivisible goal. There is where the concept of "properties" comes in.
A property can be a single form element or a joint of several form elements with a common functionality that gives them sense to be treated as a whole.

Note: to simplify, most of the cases we can refer to a single form element as being a property itself and only disambiguate when it becomes indispensable to notice its compound nature.

The primary info regarding a property is where it resides within the form, which is called its property path. For instance, for nodes we have $form['title'] which makes title the property path.

There are countless operations that could be performed to a property, from the most elementary modification to its #access, #description or #attributes to more elaborated operations that would need more details about the nature of the property beyond its property path.
It is not the same to have a property provided by the node module, than taxonomy, CCK, etc. Therefore, for many (complex) operations it will be needed to know more about it. And keeping a centralized mechanism to describe them is part of the goal of Driven API.

Then, to describe properties there are a set of sub-modules under driven/props directory, e.g: driven_node, driven_taxo, driven_cck, driven_workflow (for D7 driven_taxo and driven_cck should become driven_fields, which won't be precisely the same as CCK)
The heart of these sub-modules is to provide a proper implementation of hook_driven_properties, which is the mechanism to retrieve the meta-description of all available properties.

Having a meta-description retrieval won't be the only thing in common between modules taking advantage of Driven API. All of them will have configurable options to know whether they are expected to react to certain properties, as well as how they are expected to do so, and the underlying issue that at any time a property might become unavailable (for several reasons, e.g: a module is suddenly turned off) and yet the module should keep working (if there is anything it still can do).

Then, to know which properties are available for certain content type, the function driven_properties_available is used. But it is not such a great help if every module would have to implement its own settings page for them. Then the driven_props module comes in, to provide a centralized mechanism to setup an administrative page and a more sophisticated retrieval mechanism driven_props_get_properties (which is optional and highly recommended, but not mandatory).

As to know how the module is expected to react, there are the behaviors or policies which allow to parameterize its response beyond elementary on/off settings. An example of such behaviors would be the driven_acp module, allowing setting up Access Control Policies per role basis. This can be better understood when using the driven_nep module (where NEP stands for Node Edition Policy), which has the ability to grant/deny access to the selected properties, but without behaviors it can only turn on or off its reactions to properties, while having driven_acp enabled it will be improved with the ability to react based on existing roles.

Know, going deeper, lets walk through functions in the main modules of Driven API.

driven.module

driven_menu: Implements hook_menu.
Sets up a root menu where all global settings will reside. Every module implementing hook_global_settings_form will have its own tab (local task) under this menu.

driven_settings_form: The global settings of Driven API.
This is a default tab (default local task) under the menu created for global settings.

And this is the place when we find what might become the first question: Why do we have Access Control involved if it is also provided as a behavior?
Well, despite the fact that most modules won't alter the #access of the affected properties, they have to guarantee that they won't be touching anything beyond what they have been enabled for. And that's why there are global settings for "grant in depth"/"deny in depth" as well as some access-related functions.

The grant/deny "in depth" issue was considered "just in case" of misbehavior from other contributed modules. And should be considered an "advanced" setup, therefore I won't dig into it.

driven_form_state_value: This function is the counterpart of form_set_value.
You can read the documentation of form_set_value in core's form.inc and realize how the retrieval of a $form_state['value'] should be.

driven_properties_available: Retrieval for the available properties of certain content type.
It doesn't do anything magical. Just proper initialization of the meta-description exposed by driven/props/* modules.
Why meta-description is arranged the way it is can be questioned and/or improved. It simply is the way it is because it worked for my first incursion.

driven_build_properties_map: Truly gibberish but very important piece of code.

Let's go back to what a property path is.
If we recall the example of $form['title'] its property path was just title, that simple. And if we want to know where should that value be picked up within a $form_state['values'] it is really simple: $form_state['values']['title'].
But it isn't that simple for every kind of property. Let's start with D6 taxonomy (because it would be easily understandable) which won't exist in D7 but Fields will, and certainly fieldgroups at some point (and hopefully multigroups as well)

If we are going to point out the property path of a particular vocabulary within a node form, let's say vid=2 (the vocabulary id), then its property path could be as simple as taxonomy:2 meaning $form['taxonomy'][2], but that vocabulary can be a "free tagging" one, and then it would reside under $form['taxonomy']['tags'][2] instead. And what is even worse, it can be one thing one day, and suddenly be changed to be otherwise.
So, how should driven_taxo expose the property for this vocabulary in a uniform way recognizable in time despite the settings of the addressed vocabulary?
Well, the exposed property would be actually taxo:2, where taxo stands for the realm of the property, and in this case 2 corresponds to the targeted vid. But this isn't a property path per se, thus it needs to be translated/mapped to its proper property path in the moment the question is asked.

It is similarly for CCK. When a CCK field is at the top level of a content type its path is one, but changes once it is within a group.
An even worse, if there is multigroup involved, it isn't that easy to infer where would it reside in a $form_state['values']. It will require to be mapped differently (pending to monitor how multigroup evolves for D7)

driven_build_property_paths_tree: Builds a tree structure to easily navigate the mapped property paths.

driven_form_signature: A form element to decorate Driven API pages.

driven_assertion_failed: A primitive implementation of an assertion mechanism suited for these modules (we are not in a test case, rather under a tricky development)

Next step: driven_props. The centralized (though recommend not mandatory) mechanism for property settings page (behaviors/policies included).