Loaded fields */ public array $fields = []; /** @var array Raw field configs from registry */ public array $fieldConfigs = []; /** @var string|null Base key for options storage */ public ?string $baseKey = null; /** * WordPress default fields by object type */ public const WP_DEFAULTS = [ 'post' => [ 'post_title', 'post_excerpt', 'post_content', 'post_date', 'post_status', 'post_modified', 'post_thumbnail', 'menu_order' ], 'user' => [ 'first_name', 'last_name', 'display_name', 'description', 'user_email', ], 'term' => [ 'name', 'description' ] ]; public function __construct( int|string|null $id, string $objectType, ?string $contentType = null ) { $this->id = $id; $this->objectType = $objectType; $this->contentType = $contentType; } /** * Check if field exists in configs */ public function hasField(string $name): bool { return isset($this->fields[$name]) || isset($this->fieldConfigs[$name]); } /** * Get loaded field instance */ public function getField(string $name): ?Field { return $this->fields[$name] ?? null; } /** * Set/add a field instance */ public function setField(Field $field): self { $this->fields[$field->name] = $field; return $this; } /** * Remove a field instance */ public function removeField(string $name): self { unset($this->fields[$name]); return $this; } /** * Get field configuration */ public function getFieldConfig(string $name): ?array { if (isset($this->fieldConfigs[$name])) { return $this->fieldConfigs[$name]; } // Search nested fields (repeaters, groups) foreach ($this->fieldConfigs as $config) { if (isset($config['fields'][$name])) { return $config['fields'][$name]; } } return null; } /** * Check if field is a WordPress default */ public function isWpDefault(string $name): bool { $defaults = self::WP_DEFAULTS[$this->objectType] ?? []; return in_array($name, $defaults, true); } /** * Get all dirty (changed) fields * @return array */ public function getDirtyFields(): array { return array_filter($this->fields, fn(Field $f) => $f->isDirty); } /** * Get all invalid fields * @return array */ public function getInvalidFields(): array { return array_filter($this->fields, fn(Field $f) => !$f->isValid); } /** * Mark all loaded fields as clean */ public function markAllClean(): self { foreach ($this->fields as $field) { $field->markClean(); } return $this; } /** * Reset all fields to original values */ public function resetAll(): self { foreach ($this->fields as $field) { $field->reset(); } return $this; } /** * Check if any fields are dirty */ public function hasDirtyFields(): bool { return !empty($this->getDirtyFields()); } /** * Check if all fields are valid */ public function isValid(): bool { return empty($this->getInvalidFields()); } /** * Get all field names from configs */ public function getFieldNames(): array { return array_keys($this->fieldConfigs); } /** * Get loaded field values as array */ public function toArray(): array { $data = []; foreach ($this->fields as $name => $field) { $data[$name] = $field->value; } return $data; } }