Software Listing

Software Listing

I wanted a directory listing of access or vba add-ons for my website to share details of items I had used or reviewed.

I checked some WordPress plugins but many didn’t give the details I wanted and those that had the items were classed as premium.

I asked ChatGPT to write a plugin. After a number of iterations and testing I got this version working. It allows users to add there own product to the listing and it required approval before it will be listed.

You can see it working on this page. Its not perfect I may revisit this in the future and update this post.

When the plugin is installed it will allow two shortcodes, [product_directory_shortcode] will show the listing of products or in my case tools and addons, [product_submission_form_shortcode] which will add the input form for users to add new entries.

<?php
/*
Plugin Name: Software Listing Directory
Description: A plugin to manage and display a directory of addons for VBA.
Version: 1.0
Author: Anything Access
Author URI: https://AnythingAccess.com/software-listing
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// Activation: Create the database table
register_activation_hook(__FILE__, 'product_directory_create_table');
function product_directory_create_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'product_directory';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id MEDIUMINT(9) NOT NULL AUTO_INCREMENT,
product_name VARCHAR(255) NOT NULL,
url VARCHAR(255),
details TEXT,
price DECIMAL(10, 2),
approved TINYINT(1) DEFAULT 0,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// Add Admin Menu
add_action('admin_menu', 'product_directory_admin_menu');
function product_directory_admin_menu() {
add_menu_page(
'Product Directory',
'Product Directory',
'manage_options',
'product-directory',
'product_directory_admin_page'
);
}
// Shortcode for front-end submission
add_shortcode('product_submission_form', 'product_submission_form_shortcode');
function product_submission_form_shortcode() {
ob_start();
?>
<form method="post" action="">
<label for="product_name">Product Name:</label>
<input type="text" name="product_name" id="product_name" required><br>
<label for="url">URL:</label>
<input type="url" name="url" id="url"><br>
<label for="details">Details:</label>
<textarea name="details" id="details"></textarea><br>
<label for="price">Price:</label>
<input type="number" name="price" id="price" step="0.01"><br>
<input type="submit" name="submit_product" value="Submit">
</form>
<?php
return ob_get_clean();
}
// Handle Form Submission
add_action('init', 'handle_product_submission');
function handle_product_submission() {
if (isset($_POST['submit_product'])) {
global $wpdb;
$table_name = $wpdb->prefix . 'product_directory';
$data = [
'product_name' => sanitize_text_field($_POST['product_name']),
'url' => esc_url_raw($_POST['url']),
'details' => sanitize_textarea_field($_POST['details']),
'price' => floatval($_POST['price']),
'approved' => 0, // Require admin approval
];
$wpdb->insert($table_name, $data);
// Store a flag in the session to display the thank you message
if (!session_id()) {
session_start();
}
$_SESSION['submission_success'] = true;
// Redirect to the same page to avoid resubmission
wp_redirect($_SERVER['REQUEST_URI']);
exit;
}
}
// Display the Thank You Message
add_action('the_content', 'display_thank_you_message');
function display_thank_you_message($content) {
if (!session_id()) {
session_start();
}
if (!empty($_SESSION['submission_success'])) {
$thank_you_message = '<p>Thank you for your submission! It will be reviewed shortly.</p>';
unset($_SESSION['submission_success']); // Clear the flag after displaying the message
// Append the thank you message after the page title
return $content . $thank_you_message;
}
return $content;
}
// Admin page area
function product_directory_admin_page() {
global $wpdb;
$table_name = $wpdb->prefix . 'product_directory';
// Handle Edit Form Submission
if (isset($_POST['edit_product'])) {
$id = intval($_POST['id']);
$data = [
'product_name' => sanitize_text_field($_POST['product_name']),
'url' => esc_url_raw($_POST['url']),
'details' => sanitize_textarea_field($_POST['details']),
'price' => floatval($_POST['price']),
];
$wpdb->update($table_name, $data, ['id' => $id]);
echo '<p>Product updated successfully!</p>';
}
// Handle Approve Action
if (isset($_GET['approve'])) {
$wpdb->update($table_name, ['approved' => 1], ['id' => intval($_GET['approve'])]);
echo '<p>Product approved successfully!</p>';
}
// Handle Delete Action
if (isset($_GET['delete'])) {
$wpdb->delete($table_name, ['id' => intval($_GET['delete'])]);
echo '<p>Product deleted successfully!</p>';
}
// Display Edit Form if "Edit" is clicked
if (isset($_GET['edit'])) {
$id = intval($_GET['edit']);
$product = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $id), ARRAY_A);
if ($product) {
echo '<h2>Edit Product</h2>';
echo '<form method="post">';
echo '<input type="hidden" name="id" value="' . esc_attr($product['id']) . '">';
echo '<p><label>Product Name:</label> <input type="text" name="product_name" value="' . esc_attr($product['product_name']) . '"></p>';
echo '<p><label>URL:</label> <input type="url" name="url" value="' . esc_attr($product['url']) . '"></p>';
echo '<p><label>Details:</label> <textarea name="details">' . esc_textarea($product['details']) . '</textarea></p>';
echo '<p><label>Price:</label> <input type="number" step="0.01" name="price" value="' . esc_attr($product['price']) . '"></p>';
echo '<p><input type="submit" name="edit_product" value="Update Product"></p>';
echo '</form>';
} else {
echo '<p>Invalid product ID.</p>';
}
return; // Exit to prevent showing the table
}
// Display Product Table
$results = $wpdb->get_results("SELECT * FROM $table_name", ARRAY_A);
echo '<h1>Manage Product Directory</h1>';
echo '<table>';
echo '<tr><th>ID</th><th>Name</th><th>URL</th><th>Details</th><th>Price</th><th>Approved</th><th>Actions</th></tr>';
foreach ($results as $row) {
echo '<tr>';
echo '<td>' . $row['id'] . '</td>';
echo '<td>' . $row['product_name'] . '</td>';
echo '<td>' . $row['url'] . '</td>';
echo '<td>' . $row['details'] . '</td>';
echo '<td>' . $row['price'] . '</td>';
echo '<td>' . ($row['approved'] ? 'Yes' : 'No') . '</td>';
echo '<td>';
if (!$row['approved']) {
echo '<a href="?page=product-directory&approve=' . $row['id'] . '">Approve</a> | ';
}
echo '<a href="?page=product-directory&edit=' . $row['id'] . '">Edit</a> | ';
echo '<a href="?page=product-directory&delete=' . $row['id'] . '">Delete</a>';
echo '</td>';
echo '</tr>';
}
echo '</table>';
}
function product_directory_shortcode() {
global $wpdb;
$table_name = $wpdb->prefix . 'product_directory';
// Fetch only approved entries
$results = $wpdb->get_results("SELECT * FROM $table_name WHERE approved = 1", ARRAY_A);
// Start the card container
$output = '<div style="display: flex; flex-wrap: wrap; gap: 16px; justify-content: center;">';
foreach ($results as $row) {
$output .= '<div style="border: 1px solid #ccc; border-radius: 8px; padding: 16px; width: 100%; max-width: 300px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">';
$output .= '<h3 style="font-size: 1.2em; margin-bottom: 8px;"><a href="' . esc_url($row['url']) . '" target="_blank" style="text-decoration: none; color: #0073aa;">' . esc_html($row['product_name']) . '</a></h3>';
$output .= '<p style="font-size: 0.9em; color: #555;">' . esc_html($row['details']) . '</p>';
$output .= '</div>';
}
// Close the card container
$output .= '</div>';
return $output;
}
add_shortcode('product_directory', 'product_directory_shortcode');
add_action('wp_enqueue_scripts', 'product_submission_form_styles');
function product_submission_form_styles() {
// Ensure theme's main stylesheet is loaded
wp_enqueue_style('theme-styles', get_stylesheet_uri());
// Optional: Add custom styles if needed
wp_add_inline_style('theme-styles', '
.product-submission-form input,
.product-submission-form textarea {
width: 100%;
padding: 10px;
margin-bottom: 15px;
}
');
}

,

Leave a Reply

Your email address will not be published. Required fields are marked *