'auto'|'none'|, 'fields' => array )`. * * @since 1.0.0 */ final class Schema_Fields { /** * Cleans a meta value before it is stored. * * Fields are cleaned by the definition of the chosen type. With "automatic" the type is not * known yet, so a field is cleaned by the first definition that has its key. * * @since 1.0.0 * * @param mixed $value Raw value. * @return array{type: string, fields: array} */ public static function sanitize( $value ): array { $value = is_object( $value ) ? get_object_vars( $value ) : $value; $value = is_array( $value ) ? $value : array(); $type = isset( $value['type'] ) && is_string( $value['type'] ) ? $value['type'] : 'auto'; if ( ! in_array( $type, Type_Definitions::CHOICES, true ) && ! Type_Definitions::is_type( $type ) ) { $type = 'auto'; } $raw = isset( $value['fields'] ) && is_array( $value['fields'] ) ? $value['fields'] : array(); if ( 'none' === $type ) { return array( 'type' => 'none', 'fields' => array(), ); } $out = array(); foreach ( self::definitions( $type ) as $key => $field ) { if ( ! array_key_exists( $key, $raw ) ) { continue; } $clean = Field_Values::clean( $field, $raw[ $key ] ); if ( '' !== $clean && 0 !== $clean ) { $out[ $key ] = $clean; } } return array( 'type' => $type, 'fields' => $out, ); } /** * What a post has chosen. * * @since 1.0.0 * * @param int $post_id Post id. * @return array{type: string, fields: array} */ public static function for_post( int $post_id ): array { return self::sanitize( get_post_meta( $post_id, Keys::SCHEMA, true ) ); } /** * The type that applies to a post: its own choice, or the default of its post type. * * @since 1.0.0 * * @param WP_Post $post Post. * @param Settings $settings Settings store. * @return string One of the content types, or `none`. */ public static function type_for( WP_Post $post, Settings $settings ): string { $choice = self::for_post( $post->ID )['type']; if ( 'auto' !== $choice ) { return $choice; } return self::default_type( $post->post_type, $settings ); } /** * The default type of a post type, from the settings. * * @since 1.0.0 * * @param string $post_type Post type. * @param Settings $settings Settings store. * @return string One of the content types, or `none`. */ public static function default_type( string $post_type, Settings $settings ): string { $map = $settings->value( 'schema', 'post_types' ); if ( is_array( $map ) && isset( $map[ $post_type ] ) ) { $type = (string) $map[ $post_type ]; if ( 'none' === $type || Type_Definitions::is_type( $type ) ) { return $type; } } return Type_Definitions::default_for( $post_type ); } /** * Field definitions by key for a type, or for every type when it is not known. * * @since 1.0.0 * * @param string $type A content type, `auto` or `none`. * @return array> */ private static function definitions( string $type ): array { $types = Type_Definitions::is_type( $type ) ? array( $type ) : Type_Definitions::TYPES; $map = array(); foreach ( $types as $name ) { foreach ( Type_Definitions::fields( $name ) as $field ) { if ( ! isset( $map[ $field['key'] ] ) ) { $map[ $field['key'] ] = $field; } } } return $map; } }