label): custom badges. * - `show_if` ([ field, value ]): only show while that checkbox field has that value checked. * * `textarea` fields are lists in a code font; `prose` => true makes them a plain text box. * `heading` fields: a section title (and optional description) inside the form; never saved. * `search` fields: an AJAX multi-select (tags) over a Lookup source, `source` => products|product_cat|…. * * @since 1.0.0 */ final class Fields { /** * Render a whole schema. Consecutive toggles share one bordered group with dividers. * * @since 1.0.0 * @param string $module_id Module ID. * @param array> $fields Schema. * @param array $values Current values keyed by field ID. * @return void */ public static function render_all( $module_id, array $fields, array $values ) { $in_group = false; foreach ( $fields as $field ) { $is_toggle = 'toggle' === $field['type']; if ( $is_toggle && ! $in_group ) { echo '
'; $in_group = true; } elseif ( ! $is_toggle && $in_group ) { echo '
'; $in_group = false; } if ( ! empty( $field['show_if'] ) && ! $is_toggle ) { list( $on_field, $on_value ) = $field['show_if']; $visible = in_array( (string) $on_value, array_map( 'strval', (array) ( $values[ $on_field ] ?? array() ) ), true ); printf( '
', esc_attr( $on_field ), esc_attr( $on_value ), $visible ? '' : ' hidden' ); self::render( $module_id, $field, $values[ $field['id'] ] ?? null ); echo '
'; continue; } self::render( $module_id, $field, $values[ $field['id'] ] ?? null ); } if ( $in_group ) { echo ''; } } /** * Render one field. * * @since 1.0.0 * @param string $module_id Module ID (for unique element IDs). * @param array $field Field schema. * @param mixed $value Current value. * @return void */ public static function render( $module_id, array $field, $value ) { $id = 'apwc-' . $module_id . '-' . $field['id']; $name = $field['id']; $desc = $field['description'] ?? ''; if ( is_callable( $desc ) ) { $desc = (string) call_user_func( $desc ); // Like `warning`: evaluated only when drawn. } $warning = $field['warning'] ?? ''; if ( is_callable( $warning ) ) { $warning = (string) call_user_func( $warning ); // Evaluated only when the field is drawn. } $note = array( 'desc' => (string) $desc, 'desc_id' => $id . '-desc', 'warning' => (string) $warning, 'warn_id' => $id . '-warn', 'icon' => (string) ( $field['warning_icon'] ?? 'gauge' ), ); $badges = array(); foreach ( (array) ( $field['slow'] ?? array() ) as $slow_key ) { $badges[ (string) $slow_key ] = __( 'Slower', 'admin-powerups-for-woocommerce' ); } foreach ( (array) ( $field['badges'] ?? array() ) as $badge_key => $badge_label ) { $badges[ (string) $badge_key ] = (string) $badge_label; } $type = $field['type']; switch ( $type ) { case 'heading': ?>

/>
>
$label ) : ?>
'; printf( '', esc_attr( $id ), esc_html( $field['label'] ) ); switch ( $type ) { case 'select': echo '
'; echo ''; Icons::render( 'chevron-right', 'apwc-select__chevron' ); echo '
'; break; case 'number': printf( ''; break; case 'textarea': printf( ''; break; case 'text': printf( ''; break; case 'date': printf( ''; break; default: /** * Render a custom field type's control. Print a control named `$field['id']`. * * @since 1.0.0 * @param array $field Field schema. * @param mixed $value Current value. * @param string $id Element ID to use. */ do_action( 'apwc_render_field_' . $type, $field, $value, $id ); } self::help( $note ); self::warning( $note ); echo ''; } /** * Reorderable checklist: tick items and drag them (or use the move buttons) to set their order. * Checked items come first in saved order; the value is the checked keys in list order. * Enhanced by admin.js; without JS it still works as a plain checklist. * * @since 1.0.0 * @param string $id Element ID. * @param string $name Field name. * @param array $field Schema. * @param string[] $value Checked keys, in order. * @param array $badges Badges per key. * @param array $note Description and warning (see note()). * @return void */ private static function render_sortable( $id, $name, array $field, array $value, array $badges, array $note ) { $options = array_map( 'strval', (array) $field['options'] ); $keys = array_keys( $options ); $slow = array_map( 'strval', (array) ( $field['slow'] ?? array() ) ); $ordered = array_merge( array_values( array_intersect( $value, array_map( 'strval', $keys ) ) ), array_diff( array_map( 'strval', $keys ), $value ) ); ?>
>

$field Schema. * @param string[] $value Selected IDs. * @param array $note Description and warning (see note()). * @return void */ private static function render_search( $id, $name, array $field, array $value, array $note ) { $selected = Lookup::labels( (string) ( $field['source'] ?? '' ), $value ); $list_id = $id . '-list'; ?> $note Description and warning: desc, desc_id, warning, warn_id, icon. * @return void */ private static function aria( array $note ) { $ids = trim( ( '' !== $note['desc'] ? $note['desc_id'] : '' ) . ' ' . ( '' !== $note['warning'] ? $note['warn_id'] : '' ) ); if ( '' !== $ids ) { echo ' aria-describedby="' . esc_attr( $ids ) . '"'; } } /** * Print the field's description paragraph, if any. * * @since 1.0.0 * @param array $note Description and warning. * @return void */ private static function help( array $note ) { if ( '' !== $note['desc'] ) { echo '

' . esc_html( $note['desc'] ) . '

'; } } /** * Print the field's amber warning, if any. * * @since 1.0.0 * @param array $note Description and warning. * @return void */ private static function warning( array $note ) { if ( '' === $note['warning'] ) { return; } echo '

'; Icons::render( $note['icon'] ); echo '' . esc_html( $note['warning'] ) . '

'; } /** * A stored value as text for a single-value control. Anything that isn't a scalar (a list * saved by an older version or another plugin) shows as empty instead of "Array". * * @since 1.0.0 * @param mixed $value Stored value. * @return string */ private static function scalar( $value ) { return Str::scalar( $value ); } /** * A stored value as a list of strings for list controls. A single scalar becomes a one-item * list; nested values are dropped. * * @since 1.0.0 * @param mixed $value Stored value. * @return string[] */ private static function strings( $value ) { return array_values( Str::scalars( (array) $value ) ); } }