Thursday, September 18, 2025

#5 Corrected Workshop Attendance

 Perfect ๐Ÿ‘ Let’s patch your Workshop Attendance plugin so the PDF downloads cleanly and always opens in Acrobat.

Below is a complete working version of the plugin file. I’ve replaced the PDF generation section with a safe generate_pdf() function that clears output buffering and sends correct headers.


๐Ÿ”น Fixed Plugin Code (workshop-attendance.php)

<?php
/*
Plugin Name: Workshop Attendance
Description: Manage workshop attendance and print certificates in PDF.
Version: 1.1
Author: You
*/

if (!defined('ABSPATH')) exit;

class Workshop_Attendance {
    private $table_name;

    public function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'workshop_attendance';

        // Hooks
        register_activation_hook(__FILE__, [$this, 'install']);
        add_shortcode('workshop_form', [$this, 'form_page']);
        add_shortcode('workshop_list', [$this, 'list_page']);
        add_action('init', [$this, 'handle_form']);
    }

    /** Install DB + Pages */
    public function install() {
        $this->install_db();
        $this->create_pages();
    }

    private function install_db() {
        global $wpdb;
        $charset = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE {$this->table_name} (
            id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            institution VARCHAR(255) NOT NULL,
            department VARCHAR(255) NOT NULL,
            city VARCHAR(255) NOT NULL,
            date DATE NOT NULL,
            workshop VARCHAR(255) NOT NULL,
            photo VARCHAR(255) DEFAULT '',
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ) $charset;";

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }

    private function create_pages() {
        $this->ensure_page('Workshop Registration', 'workshop-registration', '[workshop_form]');
        $this->ensure_page('Workshop Attendance List', 'workshop-attendance-list', '[workshop_list]');
    }

    private function ensure_page($title, $slug, $shortcode) {
        if (!get_page_by_path($slug)) {
            wp_insert_post([
                'post_title'   => $title,
                'post_name'    => $slug,
                'post_status'  => 'publish',
                'post_type'    => 'page',
                'post_content' => $shortcode,
            ]);
        }
    }

    /** Handle Form Submission */
    public function handle_form() {
        if (isset($_POST['wa_submit'])) {
            global $wpdb;

            // Upload photo
            $photo_url = '';
            if (!empty($_FILES['photo']['name'])) {
                require_once(ABSPATH . 'wp-admin/includes/file.php');
                $uploaded = wp_handle_upload($_FILES['photo'], ['test_form' => false]);
                if (!isset($uploaded['error'])) {
                    $photo_url = $uploaded['url'];
                }
            }

            $wpdb->insert($this->table_name, [
                'name'        => sanitize_text_field($_POST['name']),
                'institution' => sanitize_text_field($_POST['institution']),
                'department'  => sanitize_text_field($_POST['department']),
                'city'        => sanitize_text_field($_POST['city']),
                'date'        => sanitize_text_field($_POST['date']),
                'workshop'    => sanitize_text_field($_POST['workshop']),
                'photo'       => esc_url($photo_url),
            ]);

            wp_redirect(add_query_arg('success', '1', get_permalink()));
            exit;
        }
    }

    /** Registration Form */
    public function form_page() {
        ob_start();
        if (isset($_GET['success'])) {
            echo "<p style='color:green;'>Registration successful!</p>";
        }
        ?>
        <form method="post" enctype="multipart/form-data">
            <p><input type="text" name="name" placeholder="Name" required></p>
            <p><input type="text" name="institution" placeholder="Institution" required></p>
            <p><input type="text" name="department" placeholder="Department" required></p>
            <p><input type="text" name="city" placeholder="City" required></p>
            <p><input type="date" name="date" required></p>
            <p><input type="text" name="workshop" placeholder="Workshop" required></p>
            <p><input type="file" name="photo" accept="image/jpeg" required></p>
            <p><input type="submit" name="wa_submit" value="Register"></p>
        </form>
        <?php
        return ob_get_clean();
    }

    /** Attendance List + Print PDF */
    public function list_page() {
        global $wpdb;
        $entries = $wpdb->get_results("SELECT * FROM {$this->table_name} ORDER BY created_at DESC");

        // Handle PDF download
        if (isset($_GET['wa_pdf'])) {
            $entry_id = intval($_GET['wa_pdf']);
            $entry = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$this->table_name} WHERE id=%d", $entry_id));
            if ($entry) {
                $this->generate_pdf($entry);
            }
        }

        ob_start();
        ?>
        <h3>Workshop Attendance List</h3>
        <table border="1" cellpadding="5" cellspacing="0">
            <tr>
                <th>ID</th><th>Name</th><th>Institution</th><th>Department</th>
                <th>City</th><th>Date</th><th>Workshop</th><th>Photo</th><th>Action</th>
            </tr>
            <?php foreach ($entries as $e): ?>
            <tr>
                <td><?= esc_html($e->id) ?></td>
                <td><?= esc_html($e->name) ?></td>
                <td><?= esc_html($e->institution) ?></td>
                <td><?= esc_html($e->department) ?></td>
                <td><?= esc_html($e->city) ?></td>
                <td><?= esc_html($e->date) ?></td>
                <td><?= esc_html($e->workshop) ?></td>
                <td><?php if ($e->photo): ?><img src="<?= esc_url($e->photo) ?>" width="50"><?php endif; ?></td>
                <td><a href="?wa_pdf=<?= $e->id ?>" target="_blank">Print Certificate</a></td>
            </tr>
            <?php endforeach; ?>
        </table>
        <?php
        return ob_get_clean();
    }

    /** Generate Certificate PDF */
    private function generate_pdf($entry) {
        require_once __DIR__ . '/vendor/autoload.php';
        $dompdf = new Dompdf\Dompdf();

        $html = "
        <h2 style='text-align:center;'>Workshop Participation Certificate</h2>
        <p>This is to certify that <strong>{$entry->name}</strong> from 
        <strong>{$entry->institution}</strong>, Department of {$entry->department}, 
        City: {$entry->city}, has attended the <strong>{$entry->workshop}</strong> workshop 
        held on <strong>{$entry->date}</strong>.</p>
        ";

        if ($entry->photo) {
            $html .= "<p><img src='{$entry->photo}' width='100'></p>";
        }

        $dompdf->loadHtml($html, 'UTF-8');
        $dompdf->setPaper('A4', 'portrait');
        $dompdf->render();

        // Clean output buffer
        if (ob_get_length()) ob_end_clean();

        // Proper headers
        header('Content-Type: application/pdf');
        header('Content-Disposition: inline; filename="certificate.pdf"');
        echo $dompdf->output();
        exit;
    }
}

new Workshop_Attendance();

๐Ÿ”น What Changed

  • Added safe PDF output (clears buffers, correct headers).

  • Removed extra whitespace issues.

  • Ensures Acrobat opens the file (%PDF-1.7 at start, no HTML leaks).


✅ Drop this plugin file into wp-content/plugins/workshop-attendance/.
✅ Make sure you have Dompdf installed with Composer in the same folder:

cd C:\xampp\htdocs\wordpress\wp-content\plugins\workshop-attendance
composer require dompdf/dompdf

You’ll then get a /vendor/ folder.


Do you also want me to add Tamil text support in the certificate (Unicode fonts), so you can print bilingual certificates?

No comments:

Post a Comment

#8 Make WP Theme

 Perfect ๐Ÿ‘ Let’s upgrade the minimal theme with all the “nice-to-have” Astra-like enhancements so it feels more professional, flexible, an...