* * This is similar to using `round()` but the precision is more fine-grained. * * @since 5.3.0 * * @param int|float $expected The expected value. * @param int|float $actual The actual number. * @param int|float $precision Optional. The allowed variation. Default 1. * @return bool Whether the numbers match within the specified precision. */ function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) { return abs( (float) $expected - (float) $actual ) <= $precision; } /** * Creates and returns the markup for an admin notice. * * @since 6.4.0 * * @param string $message The message. * @param array $args { * Optional. An array of arguments for the admin notice. Default empty array. * * @type string $type Optional. The type of admin notice. * For example, 'error', 'success', 'warning', 'info'. * Default empty string. * @type bool $dismissible Optional. Whether the admin notice is dismissible. Default false. * @type string $id Optional. The value of the admin notice's ID attribute. Default empty string. * @type string[] $additional_classes Optional. A string array of class names. Default empty array. * @type string[] $attributes Optional. Additional attributes for the notice div. Default empty array. * @type bool $paragraph_wrap Optional. Whether to wrap the message in paragraph tags. Default true. * } * @return string The markup for an admin notice. */ function wp_get_admin_notice( $message, $args = array() ) { $defaults = array( 'type' => '', 'dismissible' => false, 'id' => '', 'additional_classes' => array(), 'attributes' => array(), 'paragraph_wrap' => true, ); $args = wp_parse_args( $args, $defaults ); /** * Filters the arguments for an admin notice. * * @since 6.4.0 * * @param array $args The arguments for the admin notice. * @param string $message The message for the admin notice. */ $args = apply_filters( 'wp_admin_notice_args', $args, $message ); $id = ''; $classes = 'notice'; $attributes = ''; if ( is_string( $args['id'] ) ) { $trimmed_id = trim( $args['id'] ); if ( '' !== $trimmed_id ) { $id = 'id="' . $trimmed_id . '" '; } } if ( is_string( $args['type'] ) ) { $type = trim( $args['type'] ); if ( str_contains( $type, ' ' ) ) { _doing_it_wrong( __FUNCTION__, sprintf( /* translators: %s: The "type" key. */ __( 'The %s key must be a string without spaces.' ), 'type' ), '6.4.0' ); } if ( '' !== $type ) { $classes .= ' notice-' . $type; } } if ( true === $args['dismissible'] ) { $classes .= ' is-dismissible'; } if ( is_array( $args['additional_classes'] ) && ! empty( $args['additional_classes'] ) ) { $classes .= ' ' . implode( ' ', $args['additional_classes'] ); } if ( is_array( $args['attributes'] ) && ! empty( $args['attributes'] ) ) { $attributes = ''; foreach ( $args['attributes'] as $attr => $val ) { if ( is_bool( $val ) ) { $attributes .= $val ? ' ' . $attr : ''; } elseif ( is_int( $attr ) ) { $attributes .= ' ' . esc_attr( trim( $val ) ); } elseif ( $val ) { $attributes .= ' ' . $attr . '="' . esc_attr( trim( $val ) ) . '"'; } } } if ( false !== $args['paragraph_wrap'] ) { $message = "

$message

"; } $markup = sprintf( '
%4$s
', $id, $classes, $attributes, $message ); /** * Filters the markup for an admin notice. * * @since 6.4.0 * * @param string $markup The HTML markup for the admin notice. * @param string $message The message for the admin notice. * @param array $args The arguments for the admin notice. */ return apply_filters( 'wp_admin_notice_markup', $markup, $message, $args ); } /** * Outputs an admin notice. * * @since 6.4.0 * * @param string $message The message to output. * @param array $args { * Optional. An array of arguments for the admin notice. Default empty array. * * @type string $type Optional. The type of admin notice. * For example, 'error', 'success', 'warning', 'info'. * Default empty string. * @type bool $dismissible Optional. Whether the admin notice is dismissible. Default false. * @type string $id Optional. The value of the admin notice's ID attribute. Default empty string. * @type string[] $additional_classes Optional. A string array of class names. Default empty array. * @type string[] $attributes Optional. Additional attributes for the notice div. Default empty array. * @type bool $paragraph_wrap Optional. Whether to wrap the message in paragraph tags. Default true. * } */ function wp_admin_notice( $message, $args = array() ) { /** * Fires before an admin notice is output. * * @since 6.4.0 * * @param string $message The message for the admin notice. * @param array $args The arguments for the admin notice. */ do_action( 'wp_admin_notice', $message, $args ); echo wp_kses_post( wp_get_admin_notice( $message, $args ) ); } /** * Checks if a mime type is for a HEIC/HEIF image. * * @since 6.7.0 * * @param string $mime_type The mime type to check. * @return bool Whether the mime type is for a HEIC/HEIF image. */ function wp_is_heic_image_mime_type( $mime_type ) { $heic_mime_types = array( 'image/heic', 'image/heif', 'image/heic-sequence', 'image/heif-sequence', ); return in_array( $mime_type, $heic_mime_types, true ); } /** * Returns a cryptographically secure hash of a message using a fast generic hash function. * * Use the wp_verify_fast_hash() function to verify the hash. * * This function does not salt the value prior to being hashed, therefore input to this function must originate from * a random generator with sufficiently high entropy, preferably greater than 128 bits. This function is used internally * in WordPress to hash security keys and application passwords which are generated with high entropy. * * Important: * * - This function must not be used for hashing user-generated passwords. Use wp_hash_password() for that. * - This function must not be used for hashing other low-entropy input. Use wp_hash() for that. * * The BLAKE2b algorithm is used by Sodium to hash the message. * * @since 6.8.0 * * @throws TypeError Thrown by Sodium if the message is not a string. * * @param string $message The message to hash. * @return string The hash of the message. */ function wp_fast_hash( #[\SensitiveParameter] string $message ): string { $hashed = sodium_crypto_generichash( $message, 'wp_fast_hash_6.8+', 30 ); return '$generic$' . sodium_bin2base64( $hashed, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING ); } /** * Checks whether a plaintext message matches the hashed value. Used to verify values hashed via wp_fast_hash(). * * The function uses Sodium to hash the message and compare it to the hashed value. If the hash is not a generic hash, * the hash is treated as a phpass portable hash in order to provide backward compatibility for passwords and security * keys which were hashed using phpass prior to WordPress 6.8.0. * * @since 6.8.0 * * @throws TypeError Thrown by Sodium if the message is not a string. * * @param string $message The plaintext message. * @param string $hash Hash of the message to check against. * @return bool Whether the message matches the hashed message. */ function wp_verify_fast_hash( #[\SensitiveParameter] string $message, string $hash ): bool { if ( ! str_starts_with( $hash, '$generic$' ) ) { // Back-compat for old phpass hashes. require_once ABSPATH . WPINC . '/class-phpass.php'; return ( new PasswordHash( 8, true ) )->CheckPassword( $message, $hash ); } return hash_equals( $hash, wp_fast_hash( $message ) ); } /** * Generates a unique ID based on the structure and values of a given array. * * This function serializes the array into a JSON string and generates a hash * that serves as a unique identifier. Optionally, a prefix can be added to * the generated ID for context or categorization. * * @since 6.8.0 * * @param array $data The input array to generate an ID from. * @param string $prefix Optional. A prefix to prepend to the generated ID. Default ''. * * @return string The generated unique ID for the array. */ function wp_unique_id_from_values( array $data, string $prefix = '' ): string { if ( empty( $data ) ) { _doing_it_wrong( __FUNCTION__, sprintf( /* translators: %s: parameter name. */ __( 'The %s argument must not be empty.' ), '$data' ), '6.8.0' ); } $serialized = wp_json_encode( $data ); $hash = substr( md5( $serialized ), 0, 8 ); return $prefix . $hash; }