withPersistenceIdentifier($persistenceIdentifier) ->withFileUid($fileUid); } public function toArray(): array { return [ 'identifier' => $this->identifier, 'type' => $this->type, 'label' => $this->name, 'name' => $this->name, 'prototypeName' => $this->prototypeName, 'persistenceIdentifier' => $this->persistenceIdentifier ?? $this->identifier, 'invalid' => $this->invalid, 'readOnly' => $this->readOnly, 'removable' => $this->removable, 'storageType' => $this->storageType, 'storageLocation' => $this->storageLocation ?? $this->storageType, 'duplicateIdentifier' => $this->duplicateIdentifier, 'fileUid' => $this->fileUid, 'referenceCount' => $this->referenceCount, 'editUrl' => $this->editUrl, 'actions' => $this->actions, ]; } private function with(array $changes): self { return new self( identifier: $changes['identifier'] ?? $this->identifier, type: $changes['type'] ?? $this->type, name: $changes['name'] ?? $this->name, prototypeName: $changes['prototypeName'] ?? $this->prototypeName, persistenceIdentifier: $changes['persistenceIdentifier'] ?? $this->persistenceIdentifier, invalid: $changes['invalid'] ?? $this->invalid, readOnly: $changes['readOnly'] ?? $this->readOnly, removable: $changes['removable'] ?? $this->removable, storageType: $changes['storageType'] ?? $this->storageType, duplicateIdentifier: $changes['duplicateIdentifier'] ?? $this->duplicateIdentifier, fileUid: $changes['fileUid'] ?? $this->fileUid, referenceCount: $changes['referenceCount'] ?? $this->referenceCount, editUrl: $changes['editUrl'] ?? $this->editUrl, storageLocation: $changes['storageLocation'] ?? $this->storageLocation, actions: $changes['actions'] ?? $this->actions, ); } public function withPersistenceIdentifier(string $persistenceIdentifier): self { return $this->with(['persistenceIdentifier' => $persistenceIdentifier]); } public function withStorageType(string $storageType): self { return $this->with(['storageType' => $storageType]); } public function withDuplicateIdentifier(bool $duplicateIdentifier): self { return $this->with(['duplicateIdentifier' => $duplicateIdentifier]); } public function withReadOnly(bool $readOnly): self { return $this->with(['readOnly' => $readOnly]); } public function withRemovable(bool $removable): self { return $this->with(['removable' => $removable]); } public function withFileUid(?int $fileUid): self { return $this->with(['fileUid' => $fileUid]); } public function withReferenceCount(int $referenceCount): self { return $this->with(['referenceCount' => $referenceCount]); } public function withInvalid(bool $invalid): self { return $this->with(['invalid' => $invalid]); } public function withEditUrl(string $editUrl): self { return $this->with(['editUrl' => $editUrl]); } public function withStorageLocation(?string $storageLocation): self { return $this->with(['storageLocation' => $storageLocation]); } public function withActions(array $actions): self { return $this->with(['actions' => $actions]); } /** * Returns a comparable scalar value for the given sort field. * * Field names in SearchCriteria::ORDER_FIELDS are intentionally kept * identical to the property names of this class, so a dynamic lookup * is sufficient. Unknown fields yield null and are skipped by the * caller. Booleans are cast to int for correct numeric ordering. */ public function getSortableValue(string $field): int|string|null { if (!property_exists($this, $field)) { return null; } $value = $this->$field; if (is_bool($value)) { return (int)$value; } return is_int($value) || is_string($value) ? $value : null; } }