<?php if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } /** * @since 2.04 */ class FrmTableHTMLGenerator { /** * @var string * * @since 2.04 */ private $type = ''; /** * @var array * * @since 2.04 */ private $style_settings = array(); /** * @var bool * * @since 2.04 */ private $use_inline_style = true; /** * @var string * * @since 2.04 * @since 5.0.16 Changed scope from `private` to `protected`. */ protected $direction = 'ltr'; /** * @var bool * * @since 2.04 */ private $odd = true; /** * @var string * * @since 2.04 * @since 5.0.16 Changed scope from `private` to `protected`. */ protected $table_style = ''; /** * @var string * * @since 2.04 * @since 5.0.16 Changed scope from `private` to `protected`. */ protected $td_style = ''; /** * Cell padding. * * @since 6.25 * * @var string */ protected $cell_padding = '7px 9px'; /** * Table width. * * @since 6.25 * * @var string */ protected $width = ''; /** * Used to add a class in tables. Set in Pro. * * @var bool * * @since 5.4.2 */ public $is_child = false; /** * FrmTableHTMLGenerator constructor. * * @param string $type * @param array $atts */ public function __construct( $type, $atts = array() ) { $this->type = $type; if ( isset( $atts['cell_padding'] ) ) { $this->cell_padding = $atts['cell_padding']; } if ( isset( $atts['width'] ) ) { $this->width = $atts['width']; } $this->init_style_settings( $atts ); $this->init_use_inline_style( $atts ); $this->init_direction( $atts ); $this->init_table_style(); $this->init_td_style(); } /** * Set the style_settings property * * @since 2.04 * * @param array $atts * * @return void */ private function init_style_settings( $atts ) { $style_settings = array( 'border_color' => 'dddddd', 'bg_color' => 'f7f7f7', 'text_color' => '444444', 'font_size' => '12px', 'border_width' => '1px', 'alt_bg_color' => 'ffffff', ); $this->style_settings = apply_filters( 'frm_show_entry_styles', $style_settings ); foreach ( $this->style_settings as $key => $setting ) { if ( isset( $atts[ $key ] ) && $atts[ $key ] !== '' ) { $this->style_settings[ $key ] = $atts[ $key ]; } if ( $this->is_color_setting( $key ) ) { $this->style_settings[ $key ] = $this->get_color_markup( $this->style_settings[ $key ] ); } } $this->style_settings['class'] = $atts['class'] ?? ''; } /** * Set the use_inline_style property * * @since 2.04 * * @param array $atts * * @return void */ private function init_use_inline_style( $atts ) { if ( isset( $atts['inline_style'] ) && ! $atts['inline_style'] ) { $this->use_inline_style = false; } } /** * Set the direction property * * @since 2.04 * * @param array $atts * * @return void */ private function init_direction( $atts ) { if ( isset( $atts['direction'] ) && $atts['direction'] === 'rtl' ) { $this->direction = 'rtl'; } } /** * Set the table_style property * * @since 2.04 * * @return void */ private function init_table_style() { if ( $this->use_inline_style === true ) { $this->table_style = ' style="' . esc_attr( 'border-spacing:0;font-size:' . $this->style_settings['font_size'] . ';line-height:135%;' ); $this->table_style .= esc_attr( 'border-bottom:' . $this->style_settings['border_width'] . ' solid ' . $this->style_settings['border_color'] . ';' ) . '"'; } if ( ! empty( $this->style_settings['class'] ) ) { $this->table_style .= ' class="' . esc_attr( $this->style_settings['class'] ) . '"'; } if ( ! empty( $this->width ) ) { $this->table_style .= ' width="' . esc_attr( $this->width ) . '"'; } } /** * Set the td_style property * * @since 2.04 * * @return void */ private function init_td_style() { if ( $this->use_inline_style === true ) { $td_style_attributes = 'text-align:' . ( $this->direction === 'rtl' ? 'right' : 'left' ) . ';'; $td_style_attributes .= 'color:' . $this->style_settings['text_color'] . ';padding:' . $this->cell_padding . ';vertical-align:top;'; $td_style_attributes .= 'border-top:' . $this->style_settings['border_width'] . ' solid ' . $this->style_settings['border_color'] . ';'; $this->td_style = ' style="' . esc_attr( $td_style_attributes ) . '"'; } } /** * Removes border CSS from HTML. * * @since 6.25 * * @param string $html The HTML. * @param string $position The border position. Default is `top`. * * @return string */ public function remove_border( $html, $position = 'top' ) { $search = sprintf( 'border-%1$s:%2$s solid %3$s;', $position, $this->style_settings['border_width'], $this->style_settings['border_color'] ); return str_replace( $search, '', $html ); } /** * Determine if setting is for a color, e.g. text color, background color, or border color * * @since 2.05 * * @param string $setting_key Name of setting. * * @return bool */ private function is_color_setting( $setting_key ) { return str_contains( $setting_key, 'color' ); } /** * Get color markup from color setting value * * @since 2.05 * * @param string $color_markup value of a color setting, with format #FFFFF, FFFFFF, or white. * * @return string */ private function get_color_markup( $color_markup ) { $color_markup = trim( $color_markup ); // Check if each character in string is valid hex digit if ( FrmAppHelper::ctype_xdigit( $color_markup ) ) { $color_markup = '#' . $color_markup; } return $color_markup; } /** * Get the table row background color * * @since 2.04 * * @return string */ private function table_row_background_color() { return $this->odd ? $this->style_settings['bg_color'] : $this->style_settings['alt_bg_color']; } /** * Get the table row style * * @since 2.04 * @since 5.0.16 Changed scope from `private` to `protected`. * @since 6.25 Changed scope from `protected` to `public`. * * @return string */ public function tr_style() { if ( $this->type === 'shortcode' ) { $tr_style = ' style="[frm-alt-color]"'; } elseif ( $this->use_inline_style ) { $tr_style = ' style="background-color:' . $this->table_row_background_color() . ';"'; } else { $tr_style = ''; } return $tr_style; } /** * Gets table style. * * @since 6.25 * * @return string */ public function get_table_style() { return $this->table_style; } /** * Gets td style. * * @since 6.25 * * @return string */ public function get_td_style() { return $this->td_style; } /** * Switch the odd property from true to false or false to true * * @since 2.04 * @since 5.0.16 Changed scope from `private` to `protected`. * * @return void */ protected function switch_odd() { if ( $this->type !== 'shortcode' ) { $this->odd = ! $this->odd; } } /** * Generate a table header * * @since 2.04 * * @return string */ public function generate_table_header() { return '<table cellspacing="0"' . $this->table_style . '><tbody>' . "\r\n"; } /** * Generate a table footer * * @since 2.04 * * @return string */ public function generate_table_footer() { return '</tbody></table>'; } /** * Generate a two cell row for an HTML table * * @since 2.04 * * @param string $label The label. * @param string $value The value. * @param array $args Additional arguments. May include "field_type" string. * * @return string */ public function generate_two_cell_table_row( $label, $value, $args = array() ) { $row = '<tr' . $this->tr_style(); $row .= $this->add_row_class( $value === '' ); $row .= '>'; $label = '<th scope="row"' . $this->td_style . '>' . wp_kses_post( $label ) . '</th>'; $value = '<td' . $this->td_style . '>' . $this->filter_value_for_display( $value, $args ) . '</td>'; if ( 'rtl' === $this->direction ) { $row .= $value; $row .= $label; } else { $row .= $label; $row .= $value; } $row .= '</tr>' . "\r\n"; $this->switch_odd(); return $row; } /** * @param string $value * @param array $args * * @return string */ private function filter_value_for_display( $value, $args ) { if ( empty( $args['field_type'] ) ) { return wp_kses_post( $value ); } $field_object = FrmFieldFactory::get_field_type( $args['field_type'] ); return $field_object->filter_value_for_table_html( $value ); } /** * Generate a single cell row for an HTML table * * @since 2.04 * * @param string $value * * @return string */ public function generate_single_cell_table_row( $value ) { $row = '<tr' . $this->tr_style(); $row .= $this->add_row_class(); $row .= '>'; $row .= '<td colspan="2"' . $this->td_style . '>' . $value . '</td>'; $row .= '</tr>' . "\r\n"; $this->switch_odd(); return $row; } /** * Add classes to the tr. * * @since 5.4.2 * * @param bool $empty If the value in the row is blank. * * @return string */ protected function add_row_class( $empty = false ) { $class = ''; if ( $empty ) { // Only add this class on two cell rows. $class .= ' frm-empty-row'; } if ( $this->is_child ) { $class .= ' frm-child-row'; } if ( $class ) { $class = ' class="' . trim( $class ) . '"'; } return $class; } }