admin_url( 'admin-ajax.php' ) ) ); } /** * Render the shortcode: [tt24_form id="X"] * @since 1.0.0 * @param array $atts Shortcode attributes. * @return string The HTML output of the form. */ public function render_shortcode( $atts ) { // Extract the shortcode attributes, ensuring 'id' defaults to 0 $attributes = shortcode_atts( array( 'id' => 0, ), $atts, 'tt24_form' ); // SECURITY: Cast the ID to an absolute integer to prevent SQL injection $form_id = absint( $attributes['id'] ); if ( $form_id === 0 ) { return '

' . esc_html__( 'Error: Invalid 24TT Form ID.', '24tt-unrestricted-forms' ) . '

'; } global $wpdb; $table_forms = $wpdb->prefix . 'tt24_forms'; // Fetch the form strictly via prepared statement // FIX: Silencing the false-positive database warnings from the PCP tool // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching $form = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_forms} WHERE id = %d AND status = 'publish'", $form_id ) ); // phpcs:enable if ( ! $form ) { // Return nothing or a hidden comment if the form doesn't exist/is offline return ''; } // CONDITIONAL LOADING: We only enqueue the assets because we know a form is being rendered! wp_enqueue_style( 'tt24-public-css' ); wp_enqueue_script( 'tt24-submission-js' ); // BUG FIX v1.1.0: Safely Parse the JSON layout data accommodating both v1.0 and v1.1 formats $parsed_data = json_decode( $form->form_settings, true ); $fields = array(); if ( is_array( $parsed_data ) ) { if ( isset( $parsed_data['layout'] ) ) { // v1.1.0 Format: Extract just the layout array $fields = is_array( $parsed_data['layout'] ) ? $parsed_data['layout'] : array(); } else { // v1.0.0 Legacy Format: The whole parsed object is the layout $fields = $parsed_data; } } // Use output buffering to capture the HTML structure cleanly ob_start(); ?>
' . esc_html__( 'This form has no fields yet.', '24tt-unrestricted-forms' ) . '

'; } else { foreach ( $fields as $field ) { $this->render_field( $field ); } } ?>
*' : ''; echo '
'; if ( $type !== 'submit' && ! empty( $label ) ) { // Echo the label, then append the un-escaped HTML asterisk marker echo ''; } // Render the correct input based on type switch ( $type ) { // Merged cases for simple inputs case 'text': case 'email': case 'tel': // NEW: Support for Phone Numbers! case 'number': // NEW: Support for numerical limits case 'url': // NEW: Support for Website links echo ''; break; case 'textarea': echo ''; break; case 'submit': $btn_text = ! empty( $label ) ? $label : __( 'Submit', '24tt-unrestricted-forms' ); echo ''; break; } echo '
'; } } // Instantiate and initialize the frontend class $tt24_frontend = new TT24_Frontend(); $tt24_frontend->init();