Skip to content

Custom fields broken for any entity whose clientName differs from its short class name (Field::tableName() throws "EntityType not found") #1534

Description

@michalcharvat

Affects: Group-Office 6.8.x (probably 25+ too)

FieldSet exposes its target entity by the short name (core_entity.name), but custom-field code resolves it via EntityType::findByName(), which is keyed by clientName. For any entity whose getClientName() differs from its short class name (e.g. a module entity returning PackageModuleEntity instead of EntityName to stay unique across packages), the lookup misses and custom fields on that entity are unusable.

Root cause

go/core/model/FieldSet.phpdefineMapping():

->addQuery((new Query())->select("e.name AS entity")->join('core_entity', 'e', 'e.id = fs.entityId'));

That value feeds EntityType::findByName() in every consumer, e.g. Field::tableName():

$entityName = $fieldSet->getEntity();          // short name, e.g. "EntityName"
$entityType = EntityType::findByName($entityName);
if (!$entityType) {
    throw new Exception("EntityType '$entityName' not found for custom field ...");
}

But findByName() resolves by client name — EntityType::getName() returns clientName, and the cache index is built from it:

public function getName(): string { return $this->clientName; }   // EntityType
$cache['name'][$t->getName()] = $i;                               // getCache()

core_entity.name (short) and clientName diverge for any entity overriding getClientName(). Core/community entities work only because there name == clientName.

Reproduce

For an entity with getClientName() → e.g. "PackageModuleEntity" (so core_entity.name = "EntityName", clientName = "PackageModuleEntity"), add a custom field and trigger Field::tableName() (save the field / load an instance with custom fields):

Exception: EntityType 'EntityName' not found for custom field ...
EntityType::findByName("EntityName");          // false  (short name — not indexed)
EntityType::findByName("PackageModuleEntity");  // EntityType (client name — indexed)

Fix

Expose the same identifier findByName() resolves — the client name (both then read core_entity.clientName, so they always agree; no change where name == clientName):

--- a/go/core/model/FieldSet.php
+++ b/go/core/model/FieldSet.php
@@ defineMapping()
-        ->addQuery((new Query())->select("e.name AS entity")->join('core_entity', 'e', 'e.id = fs.entityId'));
+        ->addQuery((new Query())->select("e.clientName AS entity")->join('core_entity', 'e', 'e.id = fs.entityId'));
@@ defineFilters()  'entities'
-            $criteria->andWhere('e.name', 'IN', $value);
+            $criteria->andWhere('e.clientName', 'IN', $value);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions