Things that need to be rewritten at a low level:
- 2017-05-26 Conversion to/from storage format really ought to be a property of the recordset. Maybe there should be a fcFields object with fcField elements, each of which can have one or more fcFormat objects attached to it. Then instead of $rc->GetFieldValue() we could have something like $rc->GetField()->GetValue(), $rc->GetField()->GetAsFormat('storage'), etc. Also we could hide $rc->Insert() again and bring at least one large chunk of Form->SaveRecord() back into the Record class. See fcForm_DB::SaveRecord();
- This obviously suggests some changes to how Forms work as well.
- 2017-05-27 It would probably be good if there was some way to select page element classes at the top level, so you don't have to define a different page class, html class, and body class just to use a different content class.
We now have "sources", which are like tables but aren't necessarily connected to a database; we have "rows" which are like recordsets but aren't necessarily connected to a source (table).
- Each row class defines a set of fields by returning an appropriate class-string for any given field name. This lets row objects create field objects as needed, rather than having to set them up in advance.
- Each field class defines how to display and store its data (value) through helper classes -- there's a set of display classes (one per data type) and a set of storage classes (likewise).
- The helper classes are all descended from a common base class called an I/O Portal. Each Portal class knows how to translate from internal storage to output format and back.
- In the case of display portals, this means reading the POST or GET data, and knowing things like (e.g.) if no data is passed for a checkbox, that equates to an explicit "FALSE".
- In the case of storage portals, this means knowing things like the fact that a BIT field can't be set to numeric 0 or 1; it's actually either a character with values '0' or '1' or else you have to use this weird syntax which is something like b'0' / b'1'.
When loading new values into a row, existing Field objects are reused but are told to clear themselves. This is why each I/O Portal has to register itself with its home Field, so the Field can tell all its Portals to clear themselves (in order to prevent unintended state-peristence) when it is loaded.