One of the key principles in FormProcessor's functionality is that it knows
how HTML form's inputs are named. Later on in this article, I will show how we
automate naming of fields, now just take it as it is: FormProcessor's descendants
know name of the array that form's values are submitted into. Inside the member
functions of the class, this name is evaluated as...
$this->fieldPrefix . $this->Name
$this->Name is form's name that we pass as constructor's parameter.
$this->fieldPrefix is defined as data member of the class, but you can
think of it as of a constant value that remains the same throughout lifetime
of instances of the class. Its only purpose is to transparently add 'uniqueness'
to the field names, so that they do not accidentally get mixed with some other
The first thing generic constructor does is it 'smells the air around'. It assigns
global variable (whether it is set or not) with this magic name to $this->Values.
Then, if $this->Values is not empty, i.e. form's fields were submitted before,
FormProcessor decides that it is the not the first time this form is on the
arena. In this case, it calls the abstract $this->CustomCheck() member function.
Overriding this function in sub-classes allows these classes' authors to implement
whatever custom conditions checking they fancy. Of course, being a member function
of the class gives CustomCheck() access to $this->Values array, which contains
all values that form is working with as an associative array.
If overridden CustomCheck() finds error(s) that should not allow the form to
be considered as completed, it should write error messages in $this->Errors
data member. It is also treated as an associative array with the same association
as $this->Values. In other words, each submitted value has a potential error message
linked with it which, if not empty, indicates a fault in this value.
Then, and this is my favorite thing about abstract generic classes, the rest
of constructor reads like English: if the form is completed, let's somehow store
the data it has. Otherwise, let's display it (again or for the first time -
IsCompleted() returns 'false' if this is the form's first time). Of course,
StoreData() and DisplayForm() are calls to abstract member functions that should
be overridden in sub-classes. I hope you have noticed that in case form is
completed, besides storing data constructor also assigns a new value to the
global variable $wizardPage. This action tells the 'runner' - executing environment
- what form it should load next ('while' loop in runner will make another iteration).
Can you guess where the next $wizardPage's value comes from? Of course, from
an abstract function that should get overridden in a sub-class.
Meaning of the rest of the FormProcessor's machinery should become clear from
the following discussion. And now, before we attempt to build something useful
with our class, I have to explain how HTML form's inputs know the names they
should be assigned.