*/ public static function get_fields_for_post_type( string $post_type ): array { if ( ! self::is_active() ) { return array(); } $groups = acf_get_field_groups( array( 'post_type' => $post_type ) ); $fields = array(); foreach ( $groups as $group ) { foreach ( (array) acf_get_fields( $group ) as $field ) { if ( ! in_array( $field['type'], self::ALLOWED_TYPES, true ) ) { continue; } $fields[ $field['name'] ] = array( 'key' => $field['key'], 'name' => $field['name'], 'label' => $field['label'], 'type' => $field['type'], ); } } return array_values( $fields ); } /** * Unsupported fields (not in ALLOWED_TYPES or ORGANIZATIONAL_TYPES), * surfaced as a notice so a site owner knows why e.g. a Repeater field * doesn't show in the checklist. * * @return array */ public static function get_unsupported_fields_for_post_type( string $post_type ): array { if ( ! self::is_active() ) { return array(); } $groups = acf_get_field_groups( array( 'post_type' => $post_type ) ); $fields = array(); foreach ( $groups as $group ) { foreach ( (array) acf_get_fields( $group ) as $field ) { if ( in_array( $field['type'], self::ALLOWED_TYPES, true ) || in_array( $field['type'], self::ORGANIZATIONAL_TYPES, true ) ) { continue; } $fields[ $field['name'] ] = array( 'label' => $field['label'], 'type' => $field['type'], ); } } return array_values( $fields ); } /** * Field groups whose Location rules target a `mfs_*` post type that * no longer exists — happens when a Map Type is deleted and recreated * (e.g. after a DB reset): the new Map Type gets a new internal id, so * its CPT is a different post type and the old group is left pointing * at nothing. Detection only — nothing here repoints it automatically. * * @return array */ public static function get_orphaned_field_groups(): array { if ( ! self::is_active() ) { return array(); } $orphans = array(); foreach ( (array) acf_get_field_groups() as $group ) { foreach ( (array) ( $group['location'] ?? array() ) as $rule_group ) { foreach ( (array) $rule_group as $rule ) { $post_type = ( 'post_type' === ( $rule['param'] ?? '' ) ) ? (string) ( $rule['value'] ?? '' ) : ''; if ( '' === $post_type || 0 !== strpos( $post_type, CPT::PREFIX ) || post_type_exists( $post_type ) ) { continue; } $orphans[ $group['key'] ] = array( 'key' => $group['key'], 'title' => $group['title'], 'post_type' => $post_type, 'edit_url' => admin_url( 'post.php?post=' . (int) $group['ID'] . '&action=edit' ), ); } } } return array_values( $orphans ); } // PRO-only types (Repeater, Gallery, etc.) aren't registered when only // ACF free is active, so acf_get_field_type_prop() returns nothing for // them — title-case the raw slug instead of ACF's generic "Unknown". public static function field_type_label( string $type ): string { $label = function_exists( 'acf_get_field_type_prop' ) ? acf_get_field_type_prop( $type, 'label' ) : null; return $label ? $label : ucwords( str_replace( '_', ' ', $type ) ); } }