*/ public function details_from( $finding_or_json ) { if ( is_array( $finding_or_json ) ) { $raw = isset( $finding_or_json['details_json'] ) ? $finding_or_json['details_json'] : ''; } else { $raw = $finding_or_json; } $decoded = json_decode( (string) $raw, true ); return is_array( $decoded ) ? $decoded : array(); } /** * Human-readable coupon discount type label. * * @param string $type WooCommerce discount type. * @return string */ public function coupon_type_label( $type ) { switch ( (string) $type ) { case 'percent': return __( 'Percentage discount', 'marginbeacon' ); case 'fixed_product': return __( 'Fixed product discount', 'marginbeacon' ); case 'fixed_cart': return __( 'Fixed cart discount', 'marginbeacon' ); case '': return '—'; default: return (string) $type; } } /** * Format configured coupon amount (not effective line discount). * * @param string $type Discount type. * @param string|null $amount Configured amount. * @param string|null $currency Optional ISO currency for fixed amounts. * @return string */ public function format_coupon_amount( $type, $amount, $currency = null ) { if ( null === $amount || '' === (string) $amount ) { return '—'; } $type = (string) $type; if ( 'percent' === $type ) { $raw = trim( (string) $amount ); if ( false !== strpos( $raw, '.' ) ) { $raw = rtrim( rtrim( $raw, '0' ), '.' ); } if ( '' === $raw ) { $raw = '0'; } return $raw . '%'; } if ( in_array( $type, array( 'fixed_product', 'fixed_cart' ), true ) ) { return $this->format_money( (string) $amount, $currency ); } return (string) $amount; } /** * Product label prefering scan-time snapshot. * * @param array $finding Finding row. * @param array $details Decoded details. * @return string */ public function product_label( array $finding, array $details ) { if ( ! empty( $details['product_name'] ) ) { return (string) $details['product_name']; } $entity_type = isset( $finding['entity_type'] ) ? (string) $finding['entity_type'] : ''; if ( 'coupon' === $entity_type ) { return '—'; } $entity_id = isset( $finding['entity_id'] ) ? (int) $finding['entity_id'] : 0; if ( $entity_id > 0 && function_exists( 'get_the_title' ) ) { $title = get_the_title( $entity_id ); if ( is_string( $title ) && '' !== $title ) { return $title; } } if ( $entity_id > 0 ) { return '#' . $entity_id; } return '—'; } /** * Coupon label(s) from details (single or pairwise snapshot). * * @param array $details Decoded details. * @return string */ public function coupon_label( array $details ) { if ( ! empty( $details['coupon_code'] ) ) { return (string) $details['coupon_code']; } $a = isset( $details['coupon_a_code'] ) ? (string) $details['coupon_a_code'] : ''; $b = isset( $details['coupon_b_code'] ) ? (string) $details['coupon_b_code'] : ''; if ( '' !== $a || '' !== $b ) { return trim( $a . ( '' !== $a && '' !== $b ? ' + ' : '' ) . $b ); } if ( ! empty( $details['coupon_id'] ) ) { return '#' . (int) $details['coupon_id']; } return '—'; } /** * HTML for Product cell (edit link when permitted and entity exists). * * @param array $finding Finding row. * @param array $details Decoded details. * @return string Safe HTML. */ public function product_cell_html( array $finding, array $details ) { $label = $this->product_label( $finding, $details ); $entity_type = isset( $finding['entity_type'] ) ? (string) $finding['entity_type'] : ''; if ( 'coupon' === $entity_type ) { return esc_html( $label ); } $link_id = $this->product_edit_target_id( $finding, $details ); $url = $this->edit_url_if_allowed( $link_id, 'product' ); if ( null === $url ) { return esc_html( $label ); } return sprintf( '%2$s', esc_url( $url ), esc_html( $label ) ); } /** * HTML for Coupon cell. * * @param array $details Decoded details. * @return string Safe HTML. */ public function coupon_cell_html( array $details ) { // Pairwise: show codes as plain text (pair UI remains above the table). if ( ! empty( $details['coupon_a_code'] ) || ! empty( $details['coupon_b_code'] ) ) { return esc_html( $this->coupon_label( $details ) ); } $label = $this->coupon_label( $details ); $id = isset( $details['coupon_id'] ) ? (int) $details['coupon_id'] : 0; $url = $this->edit_url_if_allowed( $id, 'shop_coupon' ); if ( null === $url ) { return esc_html( $label ); } return sprintf( '%2$s', esc_url( $url ), esc_html( $label ) ); } /** * Coupon type cell text. * * @param array $details Decoded details. * @param string|null $currency Finding currency (unused for type). * @return string */ public function coupon_type_cell( array $details, $currency = null ) { unset( $currency ); $type = isset( $details['coupon_discount_type'] ) ? (string) $details['coupon_discount_type'] : ''; return $this->coupon_type_label( $type ); } /** * Coupon configured amount cell text. * * @param array $details Decoded details. * @param string|null $currency Currency code. * @return string */ public function coupon_discount_cell( array $details, $currency = null ) { $type = isset( $details['coupon_discount_type'] ) ? (string) $details['coupon_discount_type'] : ''; $amount = isset( $details['coupon_amount'] ) ? (string) $details['coupon_amount'] : ''; if ( '' === $type && '' === $amount && isset( $details['coupon_amount'] ) ) { // MB007 historical: amount without type. return $this->format_money( (string) $details['coupon_amount'], $currency ); } return $this->format_coupon_amount( $type, $amount, $currency ); } /** * Parent product ID for variation edit screens; otherwise entity/product id. * * @param array $finding Finding row. * @param array $details Decoded details. * @return int */ public function product_edit_target_id( array $finding, array $details ) { $entity_type = isset( $finding['entity_type'] ) ? (string) $finding['entity_type'] : ''; $variation = ! empty( $details['variation_id'] ) ? (int) $details['variation_id'] : 0; $parent = ! empty( $details['product_id'] ) ? (int) $details['product_id'] : 0; $entity_id = isset( $finding['entity_id'] ) ? (int) $finding['entity_id'] : 0; if ( 'variation' === $entity_type || $variation > 0 ) { if ( $parent > 0 ) { return $parent; } } if ( $parent > 0 && 'product' === $entity_type ) { return $parent; } return $entity_id > 0 ? $entity_id : $parent; } /** * @param int $post_id Post ID. * @param string $context product|shop_coupon. * @return string|null Edit URL or null when not linkable. */ public function edit_url_if_allowed( $post_id, $context ) { $post_id = (int) $post_id; if ( $post_id <= 0 ) { return null; } if ( function_exists( 'get_post_status' ) ) { $status = get_post_status( $post_id ); if ( ! $status ) { return null; } } $cap = 'shop_coupon' === $context ? 'edit_shop_coupon' : 'edit_product'; if ( ! current_user_can( $cap, $post_id ) && ! current_user_can( 'edit_post', $post_id ) ) { return null; } if ( ! function_exists( 'get_edit_post_link' ) ) { return null; } $url = get_edit_post_link( $post_id, 'raw' ); if ( ! is_string( $url ) || '' === $url ) { return null; } return $url; } /** * @param string $amount Decimal string. * @param string|null $currency Currency. * @return string */ private function format_money( $amount, $currency = null ) { if ( function_exists( 'wc_price' ) ) { $args = array(); if ( is_string( $currency ) && '' !== $currency ) { $args['currency'] = $currency; } $formatted = wc_price( (float) $amount, $args ); if ( function_exists( 'wp_strip_all_tags' ) ) { return wp_strip_all_tags( (string) $formatted ); } return (string) $formatted; } if ( is_string( $currency ) && '' !== $currency ) { return $currency . ' ' . $amount; } return $amount; } }