Problem/Motivation
First, apologize to bring that issue without providing a solution to debate (yet). But I think it must be raised so developers are aware of the problem and may take it into account.
While I love the FieldMapper plugin idea, I feel its design has some issues. I didn't find a way to get the value of a single field through a mapper without processing the whole raw external entity data (ie. by calling extractEntityValuesFromRawData()
). However, I met some use cases where I needed to process a single raw value through the mapper to get its resulting "Drupal-side" value. For instance, with the xnttmulti module I developed, I wanted to be able to "join" multiple external entity types using a first storage plugin field value as the id to load another record from another storage plugin (ie. like in SQL when you join 2 different tables and have an id column for the first table that is not the id column of the other table but instead you use a foreign key column to link those 2). I could develop but I fear nobody would read it.
Another problem is related to the design of ExternalEntityStorageClientBase->query()
. I wanted to implement that method for several external entity modules I created (xntt*) but I realized that it's hard to filter on other thing than the rawdata. For instance, with xnttdb which works with SQL queries on other databases, to filter on a single given field, I would have to load each external entity to have their field value mapped and then match the query by code. Let's say I have a "student" table in an external database with an "name" column. That "name" column would be fetched by xnttdb storage client as a raw field "name" (in an external entity raw array) which is mapped to a Drupal field "field_student_name". If I got another module which would like to filter my external entity by its "field_student_name", it will call the storage query() method. But from the storage client perspective, I don't know what is mapped to "field_student_name" (imagine if the field mapper is using a JSONPath for instance!) so I don't know how to build my SQL query to filter that!
I got a similar issue with xntt files. I had a complex mapping and wanted to filter that but realized that I needed to filter on the raw field names rather than Drupal field_* fields... It is not good because it breaks the decoupling between my data model and my data storage.
Proposed resolution
I don't have a "completed idea" of what could solve my problems but I propose to discuss possible solutions here. In FieldMapperInterface, I would see a public function extractEntityFieldValueFromRawData(array $raw_data);
that would return a single Drupal (array) value form a $raw_data array (that may not be complete). Maybe a public function getMappedRawFieldNamesForEntityField(string $drupal_field_name);
that would return the list of raw field names used for the mapping of a given Drupal field. But that might be complicated to implement (nb. I also created xnttstrjp field mapper and it would be hard to implement that one...). And if unicorns or Santa Claus exist ;p , how about a public function reverseMapFieldValueToRawData($entity, $field_name);
that would return, given an external entity object and a Drupal field name, the corresponding raw array that would have generated that value. Again, something quite complex to code. Maybe another interface could be created for those and only implemented when possible and storage clients could check it that interface is implemented.
I don't know. Any better ideas?
Remaining tasks
Discuss pros/cons and other possible solutions/approaches.
API changes
To be determined.
Data model changes
Changes in FieldMapper.
[edit]: this issue is in fact a child issue of
✨
Better support for query filtering and data saving
Active
. Only the reverse-mapping might be interesting here. It needs further investigation on xnttmulti to see if this issue is still relevant when
✨
Better support for query filtering and data saving
Active
would be solved.