generators ) { return; } $this->generators = array(); // Get generators from Form_Manager (which applies the filter) if ( class_exists( Plugin::class ) && Plugin::instance()->form ) { $generators = Plugin::instance()->form->get_options_generators(); foreach ( $generators as $id => $generator ) { $this->generators[ $id ] = $generator; } } } /** * Get a generator by ID. * * @param string $id Generator ID. * * @return Base|null Generator instance or null if not found. */ public function get( string $id ): ?Base { $this->load_generators(); return $this->generators[ $id ] ?? null; } /** * Check if a generator exists. * * @param string $id Generator ID. * * @return bool */ public function has( string $id ): bool { $this->load_generators(); return isset( $this->generators[ $id ] ); } /** * Get all registered generators. * * @return Base[] */ public function get_all(): array { $this->load_generators(); return $this->generators; } /** * Get generators list for select control (id => name format). * * @return array */ public function get_list(): array { $this->load_generators(); $list = array( array( 'value' => '', 'label' => __( '-- Select generator --', 'jet-form-builder' ), ), ); foreach ( $this->generators as $generator ) { if ( ! $generator->can_generate() ) { continue; } $list[] = array( 'value' => $generator->get_id(), 'label' => $generator->get_name(), ); } return $list; } /** * Get all schemas for JS localization. * Returns detailed schema information for editor UI generation. * * @return array */ public function get_schemas_for_js(): array { $this->load_generators(); $schemas = array(); foreach ( $this->generators as $id => $generator ) { if ( $generator instanceof Base_V2 ) { // New V2 generator with full schema support $schemas[ $id ] = $generator->get_schema_for_js(); } else { // Legacy generator - create minimal schema $schemas[ $id ] = $this->create_legacy_schema( $generator ); } } return $schemas; } /** * Creates minimal schema for legacy generators. * * @param Base $generator Legacy generator instance. * * @return array */ private function create_legacy_schema( Base $generator ): array { $id = $generator->get_id(); // Special handling for known legacy generators switch ( $id ) { case 'num_range_manual': return array( 'id' => $id, 'name' => $generator->get_name(), 'schema' => array( 'generator_numbers_min' => array( 'type' => 'number', 'default' => 1, 'label' => __( 'Start of range', 'jet-form-builder' ), 'control' => 'number', 'step' => 0.01, ), 'generator_numbers_max' => array( 'type' => 'number', 'default' => 10, 'label' => __( 'End of range', 'jet-form-builder' ), 'control' => 'number', 'step' => 0.01, ), 'generator_numbers_step' => array( 'type' => 'number', 'default' => 1, 'label' => __( 'Step', 'jet-form-builder' ), 'control' => 'number', 'step' => 0.01, ), ), 'supports_update' => false, 'legacy' => false, // Has dedicated schema ); default: // Generic legacy generator with single field return array( 'id' => $id, 'name' => $generator->get_name(), 'schema' => array( 'generator_field' => array( 'type' => 'string', 'default' => '', 'label' => __( 'Field Name', 'jet-form-builder' ), 'control' => 'text', ), ), 'supports_update' => false, 'legacy' => true, ); } } /** * Get combined block attributes from all V2 generators. * Can be used to dynamically extend block.json. * * @return array */ public function get_all_block_attributes(): array { $this->load_generators(); $attributes = array(); foreach ( $this->generators as $generator ) { if ( $generator instanceof Base_V2 ) { $attributes = array_merge( $attributes, $generator->get_block_attributes() ); } } return $attributes; } /** * Generate options using specified generator. * * @param string $generator_id Generator ID. * @param array $block_attrs Block attributes. * @param array $context Optional context for auto-update. * * @return array Generated options or empty array if generator not found. */ public function generate( string $generator_id, array $block_attrs, array $context = array() ): array { $generator = $this->get( $generator_id ); if ( ! $generator ) { return array(); } if ( ! $generator->can_generate() ) { return array(); } // Use context-aware generation for V2 generators if ( $generator instanceof Base_V2 && ! empty( $context ) ) { // Priority: generator_args object (new format) > prefixed attrs (intermediate) > defaults if ( ! empty( $block_attrs['generator_args'] ) && is_array( $block_attrs['generator_args'] ) ) { $settings = $generator->parse_generator_args( $block_attrs['generator_args'] ); } else { $settings = $generator->parse_settings( $block_attrs ); } if ( isset( $block_attrs['_jfb_runtime'] ) && is_array( $block_attrs['_jfb_runtime'] ) ) { $settings['_jfb_runtime'] = $block_attrs['_jfb_runtime']; } $settings['_jfb_block_attrs'] = $block_attrs; return $generator->generate_with_context( $settings, $context ); } // Standard generation return $generator->get_values( $block_attrs ); } /** * Prevent cloning of singleton. */ private function __clone() {} /** * Prevent unserialization of singleton. * * @throws \Exception Always. */ public function __wakeup() { throw new \Exception( 'Cannot unserialize singleton' ); } }