$label, 'value' => (float) $row['value'], ); } return $rows; } } if ( ! function_exists( 'airowp_chart_donut_rows' ) ) { /** * Drop the rows a donut cannot represent, keeping colours aligned. * * A slice is a share of a total, and a negative has no share. Rendering one * as its absolute value would show a positive slice for a negative number, * so the row is removed from the chart, the legend, and the data table * alike rather than being silently misrepresented in one of them. * * @param array $rows Chart rows. * @param array $colors Series colours, positional against $rows. * @return array{rows: array, colors: array} The filtered pair. */ function airowp_chart_donut_rows( array $rows, array $colors ) { $kept_rows = array(); $kept_colors = array(); foreach ( array_values( $rows ) as $i => $row ) { if ( $row['value'] <= 0 ) { continue; } $kept_rows[] = $row; $kept_colors[] = isset( $colors[ $i ] ) ? $colors[ $i ] : ''; } return array( 'rows' => $kept_rows, 'colors' => $kept_colors, ); } } if ( ! function_exists( 'airowp_chart_meta_rows' ) ) { /** * Read a row array out of a post meta field. * * The field may hold either a JSON string or an already-decoded array. * Protected meta is never readable — it is not authored for display. * * @param string $meta_key Meta key. * @param WP_Block|null $block Block instance, for post context. * @return array Raw rows. */ function airowp_chart_meta_rows( $meta_key, $block = null ) { if ( is_protected_meta( $meta_key, 'post' ) ) { return array(); } $post_id = isset( $block->context['postId'] ) ? $block->context['postId'] : get_the_ID(); if ( ! $post_id ) { return array(); } // Same gates as the block bindings adapter and StyleBinding::resolve() // (includes/features/class-style-binding.php) so a chart cannot leak // meta those paths would withhold — e.g. a chart inside a Query Loop // that lands on a private or password-protected post. $post = get_post( $post_id ); if ( ! $post || post_password_required( $post ) ) { return array(); } if ( ! is_post_publicly_viewable( $post ) && ! current_user_can( 'read_post', $post_id ) ) { return array(); } $stored = get_post_meta( $post_id, $meta_key, true ); if ( is_array( $stored ) ) { return $stored; } if ( is_string( $stored ) && '' !== $stored ) { $decoded = json_decode( $stored, true ); return is_array( $decoded ) ? $decoded : array(); } return array(); } } if ( ! function_exists( 'airowp_chart_data_table' ) ) { /** * Render the visually-hidden data table. * * The SVG is aria-hidden, so this table is the accessible representation * of the chart. It is always emitted. * * @param array $rows Chart rows. * @param string $label Chart label. * @param int $total Source row count, to disclose a truncated chart. * @param array $format Optional. Value format options; see * airowp_chart_format_value(). * @return string Table markup. */ function airowp_chart_data_table( array $rows, $label, $total = 0, array $format = array() ) { $out = ''; $caption = '' !== $label ? $label : ''; // A truncated chart that says nothing is indistinguishable from a // complete one, and this table is the only place the full count could // have been checked, so it is where the shortfall has to be declared. if ( $total > count( $rows ) ) { $note = sprintf( /* translators: 1: rows shown, 2: rows in the source. */ __( 'Showing the first %1$s of %2$s rows.', 'airo-wp' ), number_format_i18n( count( $rows ) ), number_format_i18n( $total ) ); $caption = '' === $caption ? $note : $caption . ' ' . $note; } if ( '' !== $caption ) { $out .= ''; } $out .= ''; foreach ( $rows as $row ) { $out .= ''; } return $out . '
' . esc_html( $caption ) . '
' . esc_html__( 'Label', 'airo-wp' ) . '' . esc_html__( 'Value', 'airo-wp' ) . '
' . esc_html( $row['label'] ) . '' . esc_html( airowp_chart_format_value( $row['value'], $format ) ) . '
'; } } if ( ! function_exists( 'airowp_chart_legend' ) ) { /** * Render the legend. * * Colour is never the only channel identifying a series — the legend pairs * each swatch with its label, and the data table repeats both. * * @param array $rows Chart rows. * @param array $colors Series colours. * @return string Legend markup. */ function airowp_chart_legend( array $rows, array $colors ) { $out = ''; } }