all(); $notices[ $id ] = array( 'message' => $message, 'type' => in_array( $type, self::TYPES, true ) ? $type : 'info', 'app' => $app, ); update_option( self::OPTION, $notices, false ); } /** * Removes a notice. * * @param string $id Notice id. */ public function remove( string $id ): void { $notices = $this->all(); unset( $notices[ $id ] ); update_option( self::OPTION, $notices, false ); } /** * Removes all notices of an app. * * @param string $app App id. */ public function remove_for_app( string $app ): void { $notices = array_filter( $this->all(), static fn( array $notice ): bool => $notice['app'] !== $app ); update_option( self::OPTION, $notices, false ); } /** * All notices. * * @return array */ public function all(): array { $notices = get_option( self::OPTION, array() ); return is_array( $notices ) ? $notices : array(); } /** * Prints notices on Forensix screens only. */ public function render(): void { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; if ( null === $screen || ! str_contains( (string) $screen->id, 'forensix' ) ) { return; } foreach ( $this->all() as $notice ) { printf( '

%2$s

', esc_attr( $notice['type'] ), esc_html( $notice['message'] ) ); } } /** * Emails the site admin, at most once per throttle period per key. * * @param string $key Throttle key, e.g. "job_failed.42". * @param string $subject Subject. * @param string $body Plain-text body. * @param int $throttle Seconds before the same key may send again. * @param string $to Recipient. Empty means the site admin address. * @return bool Whether the mail was handed to the mailer. */ public function email( string $key, string $subject, string $body, int $throttle = DAY_IN_SECONDS, string $to = '' ): bool { $transient = 'forensix_mail_' . md5( $key ); if ( false !== get_transient( $transient ) ) { return false; } $sent = wp_mail( is_email( $to ) ? $to : (string) get_option( 'admin_email' ), $subject, $body ); if ( $sent ) { set_transient( $transient, 1, $throttle ); } return $sent; } }