Open TYPO3IncTeam opened 4 months ago
Currently, the API is marked as internal. We should document it when it becomes stable and official API with the then current state.
I agree we should hold off for a moment here; for the 13.4 LTS though, if it remains internal for the release, I'd like to have a very simply stub for it which just refers to the sources and the basic idea behind the Schema API, and a note that it's internal for now, what do you think?
Let's wait and see ;-) But if it stays internal, we should not document it IMHO.
We'll ask the Core team to see if/how they want it documented, for sure! :)
:information_source: View this commit on Github :busts_in_silhouette: Authored by Benni Mack benni@typo3.org :heavy_check_mark: Merged by Benni Mack benni@typo3.org
Commit message
[FEATURE] Introduce Schema API for TCA
This feature introduces a schema for reading information out of TCA, especially when working with data from the database that is TYPO3-specific only to be based on "types" (e.g. tt_content) or a specific "subtype" (e.g. the value from tt_content.CType, such as "tt_content.textmedia"), or detecting information from the global TCA definition.
The basic structure works as follows:
TcaSchemaFactory serves as the basic entry point for fetching the schema for e.g. tt_content.textmedia which then resolves all information from TCA based on the "tca" schema.
A Schema can be the main TCA table information (with everything) or the "subSchema".
A Schema contains a list of "Capabilities" (typically within "ctrl" section), possible sub schemata, and all fields registered in "showitem" (for a subtype).
The Fields are divided by the "type=..." information in TCA. Non-recognized type fields are skipped for the time being.
Only TcaSchemaFactory knows about the actual full TCA information and builds objects out of it.
Schemas and Fields are put in collections so they can never be modified after the Boostrap process is completed.
Before the schema objects are built, the RelationMap is built, which contains information which fields contain information that records "might" have a connection to another database field or table. These are then attached to the Schema and Field objects as Active and Passive Relations.
Building the Schema API as graph thus in turn needs to run two times over all TCA information and all registered FlexForm data structure definitions (as flexforms might also contain relations to tables).
Relations are built as loose DTO relation informations and not as pointers to Schema objects.
Missing parts to be evaluated later-on:
Resolves: #104002 Releases: main Change-Id: I75cf20d491364f60be7f284615eea65086085801 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75486 Tested-by: core-ci typo3@b13.com Reviewed-by: Benni Mack benni@typo3.org Reviewed-by: Christian Kuhn lolli@schwarzbu.ch Reviewed-by: Oliver Hader oliver.hader@typo3.org Tested-by: Benni Mack benni@typo3.org Tested-by: Christian Kuhn lolli@schwarzbu.ch Tested-by: Oliver Bartsch bo@cedev.de Reviewed-by: Oliver Bartsch bo@cedev.de
:heavy_plus_sign: Added files
13.2/Feature-104002-SchemaAPI.rst
```rst .. include:: /Includes.rst.txt .. _feature-104002-1718273913: ============================= Feature: #104002 - Schema API ============================= See :issue:`104002` Description =========== A new Schema API is introduced to access information about all TCA structures in a unified way. The main goal of this architecture is to reduce direct access to :php:`$GLOBALS['TCA']` after the Bootstrap process is completed. The Schema API implements the following design goals: 1. An object-oriented approach to access common TCA information such as if a database table is localizable or workspace-aware, if it has a "deleted" field ("soft-delete"), or other common functionality such as "enableFields" / "enablecolumns", which can be accessed via "Capabilities" within a Schema. 2. A unified way to access information which "types" a TCA table has available, such as "tt_content", where the "CType" field is the divisor for types, thus, allowing a Schema to have sub-schemata for a TCA Table. The API in turn then handles which fields are available for a specific "CType". An example is "tt_content" with type "textpic": The sub-schema "tt_content.textpic" only contains the fields that are registered of that "CType", such as "bodytext", which then knows it is a Rich Text Field (the default column does not have this information), or "image" (a file relation field), but the sub-schema does not contain fields that are irrelevant for this type, such as "assets" (also a file relation field). 3. An abstracted way to available TCA field types such as "input" or "select", which also takes information into account, if a select field is a selection of a static list (such as "pages.layout") or if it contains a relation to another schema or field (based on "foreign_table"). Previously, this was evaluated in many places in TYPO3 Core, and can now be reduced subsequently. Thus, Schema API can now be utilized to determine the :php:`RelationshipType` of a relational field type in a unified way without having to deal with deeply nested arrays. 4. Information about relations to other database tables or fields. This is especially useful when dealing with Inline elements or category selection fields. Schema API can find out, which fields of other schemata are pointing to one-self. Schema API differentiates between an "Active Relation" and a "Passive Relation". An Active Relation is the information that a field such as "pages.media" (a field of type "file") contains a reference to the "sys_file_reference.uid_foreign" field. Active Relations in consequence are connected to a specific field (of type :php:`RelationalFieldTypeInterface`). In turn, a "Passive Relation" is the information what other schemata/fields are pointing to a specific table or field. A common example for a "Passive Relation" is "sys_workspace_stage": The information stored in `$GLOBALS[TCA][sys_workspace_stage]` does not contain the information that this table is actually used as a reference from the database field `sys_workspace.custom_stages`, the `sys_workspace_stage` Schema now contains this information directly via :php:`TcaSchema->getPassiveRelations()`. This is possible as TcaSchemaFactory is evaluating all TCA information and holistically as a graph. Passive Relations are currently only connected to a Schema, and Active Relations to a Field or a Schema. As the Schema API fetches information solely based on TCA, a Active Relation only points to _possible_ references, however, the actual reference (does a record really have a connection to another database table) would require an actual Record instance (a database row) to evaluate this information. Relations does not know about the "Type" or "Quantity" (many-to-many etc) as this information is kept in the Field information already. For this reason, the "Relations" currently only contain a flat information structure of the table (and possibly a field) pointing TO another schema name (Active Relation) or FROM another schema name / field (Passive Relation). Schema API also parses all available FlexForm data structures in order to resolve relations as well. As a result, a field of type FlexFormField contains a list of possible "FlexFormSchema" instances, which resolve all fields, sheets and section containers within each data structure. 5. Once built, the Schema can never be changed. Whereas with TCA was possible to be overridden during runtime, all TCA is evaluated once and then cached. This is a consequence on working with an object-oriented approach. If TCA is changed after the Bootstrap process is completed, the Schema needs to be rebuilt manually, which TYPO3 Core currently does for example in some Functional Testing Scenarios. All key objects (Schema, FieldType, Capabilities) are treated as immutable DTOs and never contain cross-references to its parent objects (Sub schemata do not know information about their parent schema, a field does not know which schema it belongs to), so the only entry point is always the :php:`TcaSchemaFactory` object. This design allows the API fully cacheable on PHP level as a nested tree. 6. Low-level, not full-fletched but serves as a basis. Several API decisions were made in order to let Schema API keep only its original purpose, but can be encapsulated further in other APIs: - Schema API is not available during Bootstrap as it needs TCA to be available and fully finished. - Schema API does not contain all available TCA properties for each field type. An example is "renderType" for select fields. This information is not relevant when querying records in the Frontend, and mainly relevant for FormEngine - it is not generic enough to justify a getter method. - Extensibility: Custom field types are currently not available for the time being, until TYPO3 Core as fully migrated to Schema API. - User Permissions: Evaluating if a user has access to "tt_content.bodytext" requires information about the currently logged in user, thus not part of the Schema API. A "Permission API" should rather evaluate this information in the future. - Available options for a field. As an example, a common scenario is to find out which possible options are available for "pages.backend_layout". In TYPO3 Core an :php:`itemsProcFunc` is connected to that field in TCA. Whether there is an :php:`itemsProcFunc` is stored, but Schema API is not designed to actually execute the itemsProcFunc as it is dependent on various factors evaluated during runtime, such as the page it resides on, user permissions or PageTsConfig overrides. Schema API is currently marked as internal, as it might be changed during TYPO3 v13 development, while more parts of TYPO3 will be migrated towards Schema API. DataHandler and the Record Factory already utilize Schema API in order to reduce direct access to :php:`$GLOBALS[TCA]`. Next to TCA and FlexForms, Schema API might also be used to evaluate information for Site Configurations in the future. Impact ====== Reading and writing :php:`$GLOBALS[TCA]` within :file:`Configuration/TCA/*` and via TCA Overrides is untouched, as the API is meant for reading the information there in a unified ways. Usage ----- The API can now be used to find out information about TCA fields. public function __construct( protected readonly PageRepository $pageRepository, protected readonly TcaSchemaFactory $tcaSchemaFactory ) {} public function myMethod(string $tableName): void { if (!$this->tcaSchemaFactory->has($tableName)) { // this table is not managed via TYPO3's TCA API return; } $schema = $this->tcaSchemaFactory->get($tableName); // Find out if a table is localizable if ($schema->isLocalizable()) { // do something } // Find all registered types $types = $schema->getSubSchemata(); } Using the API improves handling for parts such as evaluating `columnsOverrides`, foreign field structures, FlexForm Schema parsing, and evaluating type fields for a database field. .. index:: PHP-API, TCA, ext:core ```