stored field, never values), rebuilt by * OptionNames::sync() after every write, so the website reads one option instead of the plugin table. Values * are always read with get_option(). * * @since 1.0.0 */ final class PublicFields { /** * @var array|null */ private static $fields; public static function optionName(): string { return Plugin::PREFIX_ . 'public_fields'; } /** * The stored field of a public option, or null. */ public static function get(string $name): ?array { $field = self::all()[$name] ?? null; // The type is checked again: an add-on (or Pro) that provided it may be gone since the list was built. return $field !== null && self::isPublic($field) ? $field : null; } /** * @return array Option name => stored field. */ public static function all(): array { if (self::$fields === null) { $stored = get_option(self::optionName(), null); self::$fields = is_array($stored) ? $stored : self::rebuild(); } return self::$fields; } /** * Build the list from the stored pages and keep it. * * @return array */ public static function rebuild(): array { self::$fields = self::fromPages(); update_option(self::optionName(), self::$fields, false); return self::$fields; } /** * @return array */ public static function fromPages(): array { if (!PageRepository::tableExists()) { return []; } $fields = []; foreach (PageRepository::pageValueRows() as $row) { foreach (PageRepository::decode($row->page_value)['pages'] ?? [] as $page) { foreach ($page['fields'] ?? [] as $field) { if (is_array($field) && !empty($field['field_name']) && self::isPublic($field)) { $fields[(string) $field['field_name']] = $field; } } } } return $fields; } /** * Forget the list of this request (tests, and after the option changed). */ public static function reset(): void { self::$fields = null; } private static function isPublic(array $field): bool { if (($field['frontend'] ?? 'no') !== 'yes') { return false; } $type = FieldRegistry::instance()->get((string) ($field['type'] ?? '')); return $type !== null && $type->supportsFrontend(); } }