DEV Community

odi pearl
odi pearl

Posted on

Q&A SECTION

  1. Explain the concept of WordPress Hooks and their practical usage. Additionally, how would you create custom hooks, and how would you remove a registered hook. Bonus:What priority/order means in WordPress Hooks ?

WordPress hooks are placeholders that allow you to add functionality into specific points of a WordPress website without affecting the code allowing developers to add or modify custom functions. They come in two types: action hooks for events like adding content, modifying database entries etc and filter hooks to modify data before it is displayed on the website.

To create a custom action hook, you can use the do_action() function while to create a custom filter hook, you can use the apply_filters() function.

Here's an example of how you can create a custom action and a custom filter hook

//using custom action hook
add_action('my_custom_action', 'my_custom_function');

function my_custom_function() {
    // Your custom functionality here
    echo "Hello, world!";
}

//using custom filter hook
function custom_filter_hook($content) {
    return apply_filters('my_custom_filter', $content);
}

// Add your custom function to the custom filter hook
add_filter('my_custom_filter', function($content) {
    return $content . " Modified";
});

// Use the custom filter hook
$content = "Original content";
echo custom_filter_hook($content); // Output: Original content Modified


Enter fullscreen mode Exit fullscreen mode

To remove a registered hook, you use remove_action() for action hooks or remove_filter() for filter hooks. Here's how you would remove a previously added action hook:

// Remove a previously added action hook
remove_action('hook_name', 'function_name');


// Remove a previously added filter hook
remove_filter('hook_name', 'function_name');
Enter fullscreen mode Exit fullscreen mode

In WordPress hooks, priority/order simply means the order in which functions are executed when hooked to the same spot. Lower priority numbers mean a function runs earlier, while higher numbers mean it runs later. By default, functions run in the order they were added, but setting priorities lets you decide when your custom code kicks in compared to others.

For example:

// Add an action with priority 10
add_action('my_custom_action', 'function1', 10);

// Add the same action with priority 20
add_action('my_custom_action', 'function2', 20);
Enter fullscreen mode Exit fullscreen mode
  1. Which tools, functions, or features in WordPress would you employ to enhance the security and safety of your plugins or themes? Please elaborate on the specific scenarios in which you would utilize each of these measures.

Preventing Direct Access: This is used to check if the constant ABSPATH is defined in PHP. If ABSPATH is not defined, it means that the file is being accessed directly without being included within the WordPress environment. In such a case, the script exits immediately, preventing any further code execution. This measure ensures that WordPress files are only accessed within the WordPress context, enhancing security by preventing unauthorized access. Here is how it is done

<?php

if (!defined('ABSPATH')){
  exit;
}
Enter fullscreen mode Exit fullscreen mode

Sanitization Functions: If you're developing a plugin that allows users to submit comments or input data through a form. You would use sanitization of functions to clean and validate user inputs such as names and comments, reducing the risk of SQL injection or XSS attacks.
Here is how to sanitize input data if there were input fields with the name ‘name’.

// Sanitize user inputs for a comment form
function sanitize_comment_input( $data ) {
    $sanitized_data = array();

    // Sanitize name
    $sanitized_data['name'] = sanitize_text_field( $data['name'] );

  // Add more sanitization for other fields if needed

    return $sanitized_data;
}
Enter fullscreen mode Exit fullscreen mode

Data Validation: Imagine you're developing a theme that includes a contact form. Before processing form submissions, you would validate user-entered data, such as email addresses and phone numbers, to ensure they adhere to the expected format and prevent potentially harmful input.
For example to validate an email you would have:

function validate_contact_email( $email ) {
    if ( filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
        return true; // Valid email
    } else {
        return false; // Invalid email
    }
}
Enter fullscreen mode Exit fullscreen mode

If the $email parameter is in a valid email format, the function returns true, indicating that the email is valid. If not, it returns false, indicating that the email is invalid.

Nonces: Nonces (number used once) are security tokens generated by WordPress to verify the origin and intent of a request. They are often used to validate form submissions and prevent CSRF (Cross-Site Request Forgery) attacks.

Regular updates and security checks: As a plugin or theme developer, you'd regularly update your codebase to address security vulnerabilities and ensure compatibility with the latest security standards. Conducting periodic security audits helps identify and mitigate potential security risks, maintaining a secure WordPress environment.

  1. Your friendly neighbor said: “Your plugin slowing down my WordPress site!”. No context whatsoever, it could be your backend codes or frontend codes, or maybe not even your codes, but something else in their website! You have access to everything: your codes that you can debug locally in your machine, the site admin credentials, the server credentials, the database server credentials, and you are allowed to do anything you want. Elaborate steps that you would do to identify the issue, What tools you would use, and what are the reasons behind using these tools.

Verify the Complaint: First, I would confirm whether the site is indeed experiencing slowdowns. I would access the WordPress site using the provided admin details and go through different pages to observe the loading times. Additionally, I might use online speed testing tools like Google PageSpeed Insights to analyze the site's performance metrics.

Check Server Resources: I would access the server using the provided credentials and examine the server's resource usage, including CPU, memory, and disk.

Review Plugins and Themes: I would review the installed plugins and themes on the WordPress site. Using the admin dashboard, I would deactivate unnecessary plugins and switch to a default WordPress theme to see if the slowdown persists. This helps determine if the issue is caused by a specific plugin or theme.

Debugging Local Environment: If the issue persists after deactivating plugins and switching themes, I would replicate the site's environment locally on my machine. I would download a copy of the site's files and database and set up a local development environment using wamp. By debugging the local environment, I can analyze the codebase, including backend and frontend scripts, for performance issues.

Database Optimization: Since database queries can often contribute to site slowdowns, I would optimize database queries by identifying and optimizing slow-running queries.

Caching and Optimization: I would review the site's caching setup and optimization techniques.

By following these steps and using various debugging tools and optimization techniques, I can effectively identify and resolve the issue causing the slowdown of the WordPress site. The combination of server monitoring, code debugging, and optimization strategies helps address performance issues and ensure a smooth and responsive user experience.

For these tasks, I would primarily utilize:

  • Google PageSpeed Insights: To assess site performance.
  • WordPress Admin Dashboard: To review plugins and themes.
  • Server Monitoring Tools: To analyze server resources.
  • Local Development Environment (WAMP): To debug code locally.
  • Database Management Tools (e.g., phpMyAdmin): To optimize database queries.
  • WordPress Caching Plugins: To optimize caching.
  1. Share your thoughts on the concept of Modern PHP. And in your view, what distinguishes a codebase as reflecting Modern PHP principles, and how would you integrate these principles into the WordPress environment?

Modern PHP" refers to the latest best practices, features, and coding standards used in PHP development. It covers a range of improvements and advancements introduced in recent versions of PHP.

Composer: Managing dependencies using Composer, a dependency management tool for PHP, to easily include third-party libraries and manage project dependencies.

To integrate Composer into WordPress:

Install Composer: Begin by installing Composer on your development environment.
Create a composer.json File: Define your project's dependencies, including any third-party libraries needed.
Manage Dependencies: Run composer install to install the dependencies specified in the composer.json file.
Autoloading: Ensure that Composer's autoloader is included in your WordPress project for automatic class loading.
Utilize within Plugins/Themes: Integrate Composer into your WordPress plugins and themes by defining dependencies in their respective composer.json files.
Version Control: Commit the composer.json and composer.lock files to version control to maintain consistency across environments.

Namespaces and Autoloading: Namespaces help prevent naming conflicts and improve code organization by grouping related classes together. Autoloading simplifies the process of including class files, reducing the need for manual require or include statements.

To integrate namespaces and autoloading into WordPress:

Namespace Declaration: Define namespaces for custom classes to prevent naming conflicts and organize code.
Autoloading Configuration: Configure Composer's autoloader in composer.json to load classes automatically.
Update Composer Autoloader: After modifying composer.json, regenerate the autoloader with composer dump-autoload.
Usage: Use namespaced classes in WordPress files without manual file inclusions.

Modern PHP Frameworks: Frameworks like Symfony, Laravel, and Laminas provide robust foundations for building web applications, offering features such as routing, templating, ORM (Object-Relational Mapping), and authentication out of the box.

Object-Oriented Programming (OOP): Modern PHP encourages the use of OOP principles such as encapsulation, inheritance, and polymorphism. By organizing code into classes and objects, developers can create more modular, maintainable, and reusable code.

Code Comments and Documentation: Maintaining proper documentation, including meaningful comments and documentation for code, is essential in modern PHP development and should be integrated into WordPress projects. This ensures code readability for future developers and serves as a helpful memory aid. Encouraging the use of inline comments, DocBlocks, readme files, changelogs, and contributor guidelines fosters consistency and collaboration within the WordPress community.

PHP Standards Recommendations (PSRs): Following PSR standards ensures consistency and interoperability across PHP projects. Adhering to PSR-1 (Basic Coding Standard), PSR-2 (Coding Style Guide), and PSR-4 (Autoloading Standard) facilitates collaboration and code maintainability.

  1. jQuery or no jQuery ?. Anyway, provide insights into how you would seamlessly integrate ReactJS into your WordPress plugin, what is the benefits and challenges of using ReactJS in the WordPress environment?.

There are several ways to integrate ReactJs such as:

Using WordPress REST API: Leveraging the WordPress REST API allows seamless communication between WordPress and external applications like ReactJS. Developers can fetch data from WordPress and render it in React components, enabling dynamic and interactive user interfaces.

Utilizing Webpack or Babel: Employing build tools like Webpack and Babel is essential for bundling and transpiling React code, ensuring compatibility with older browsers and various WordPress environments. This ensures that React components function smoothly within WordPress, providing a seamless user experience across different platforms.

And more but personally I would use ReactPress because It not only automates the React integration process but also guarantees a smooth development experience by synchronizing your local React development server with the theme of your WordPress site

  • Here is how you could integrate React in Wordpress.

Prepare Your Local Development Environment: Ensure you have Node.js, npm or yarn, For Windows users, you can use WSL-2 for experimental support.

Install ReactPress Plugin Locally: Head to the plugin installation menu in your local WordPress admin panel. Search for "ReactPress," then proceed to install and activate the plugin.

Create a New React App: Open your terminal and navigate to the apps directory within the ReactPress plugin. Use the command npx create-react-app [your-app-name] to create a new React app.

Configure Your App in WordPress: Access the ReactPress page in your WordPress admin area. Choose a unique URL Slug and configure your new app according to your preferences.

**Develop Your React App: **Utilize WordPress's REST-API or the WPGraphQL plugin to fetch data for your React app and begin development.

Build Your App for Deployment: Use the command yarn build in your terminal to build your React app for deployment.

Install ReactPress on Your Live Site: Similarly, install ReactPress on your live WordPress site as you did on your local installation.

Mirror Your App Folder on Live System: Create a matching React app folder on your live system, ensuring it shares the exact directory name used in your development server.

Upload the Build to Deploy: Finally, upload the built version of your React app to your live site, placing it within the corresponding app folder.

Advantages

Enhanced User Experience: ReactJS allows for the creation of dynamic and interactive user interfaces, improving the overall user experience of WordPress websites and applications.

Modular Development: React's component-based architecture promotes modularity and code reusability, making it easier to maintain and scale WordPress projects.

Performance Optimization: React's virtual DOM and efficient rendering process contribute to faster page load times and improved performance, enhancing site speed and responsiveness.

Vast Ecosystem: ReactJS has a large and active ecosystem with a wide range of libraries, tools, and community support, providing developers with resources to build robust and feature-rich applications.

Integration Flexibility: React can be seamlessly integrated into WordPress projects using various methods such as REST-API, shortcodes, or custom Gutenberg blocks, offering flexibility in implementation.

Challenges:

Learning Curve: Developers familiar with WordPress may face a learning curve when adopting ReactJS due to its different syntax, concepts, and development patterns.

Compatibility Issues: Ensuring compatibility with existing WordPress themes, plugins, and environments can be challenging, especially when integrating complex React components or libraries.

Performance Issues: Improper implementation of React components or excessive re-renders can lead to performance issues, impacting site speed and user experience.

SEO: Search engine optimization (SEO) may be affected if React components are not properly server-rendered or if content is dynamically loaded via client-side JavaScript, potentially affecting search engine rankings.

Complex maintenance: Managing a WordPress site with integrated React components requires additional maintenance and updates to ensure compatibility and security, adding complexity to the development process.

  1. Automated Testing and WordPress Coding Standards:Outline the importance of Automated Testing. With the best of your knowledge and experience, what tools or framework or libraries that you will use to achieve Automated Testing within your WordPress project? How familiar are you with WordPress Coding Standards, and how do you ensure your codebase consistently aligns with them? How would you integrate both Testing and Coding Standards into CI/CD ? Bonus: How would you maintain the quality of the Automated Testing?

The importance of Automated testing includes:
Saves time and cost: Automated testing saves time and money by eliminating the need to manually repeat tests after each code modification.
Tests can be run repeatedly at no additional cost and are much faster than manual tests, reducing the time to run repetitive tests from days to hours.
Increases Test Coverage: Automated testing increases the depth and scope of tests, improving software quality.
Lengthy tests that are often avoided during manual testing can be run unattended and on multiple computers with different configurations.
Automation can execute thousands of complex test cases during every test run, providing coverage that is impossible with manual tests.

Improved Accuracy: Automated tests perform the same steps precisely every time they are executed and never forget to record detailed results.
Testers have more time to create new automated tests and deal with complex features, improving overall accuracy.

Support for Developers and Testers: Shared automated tests can be used by developers to catch problems quickly before sending to QA.
Tests can run automatically whenever source code changes are checked in, notifying the team or developer if they fail.
These features save developers time and increase their confidence in the code they produce.

  • With my experience, I use PHPUnit as the primary tool for achieving automated testing within a WordPress project. PHPUnit is a widely-used testing framework for PHP and it is good for writing and executing unit tests in WordPress development. It is easy to use and has many features that makes it a good choice for verifying the functionality and behavior of individual units of code, such as functions or methods.

Some of the wordpress coding standards I use are:

Use of Linters and Code Sniffers: I utilize tools such as PHP CodeSniffer (PHPCS), ESLint for JavaScript, and Stylelint for CSS. These tools automatically scan my code for violations of coding standards and provide feedback on areas that need improvement.

IDE/Editor Integration: I configure my integrated development environment (IDE) or code editor to highlight coding standard violations in real-time as I write code. This immediate feedback helps me correct issues as I go, ensuring that my code remains compliant with the standards.

Continuous Integration/Continuous Deployment (CI/CD): I integrate automated code quality checks into CI/CD pipelines to enforce coding standards compliance. This ensures that code changes are checked against coding standards before being merged into the main codebase and deployed to production.

How i would integrate both testing and coding standards into CI/CD:

Automated Testing: I set up automated tests using frameworks using the PHPUnit , and trigger them automatically when code changes are pushed.

Code Quality Checks: Normally I use ESLint to scan for coding standard violations. Configure the pipeline to fail if violations are detected, preventing further deployment.

Review: I allow my team members to review code and ensure it is approved before merging changes into the main codebase.

Continuous Improvement: I continuously monitor and evaluate the effectiveness of the CI/CD pipeline. Collect metrics on test coverage, code quality, and deployment success rates.

Here are ways i would maintain quality of automated testing

  • Monitor test coverage and prioritize improvements in critical areas.
  • Use parameterized and data-driven tests to increase coverage.
  • Automate test maintenance tasks to adapt to changes in the application.
  • Integrate tests into CI/CD pipelines for frequent feedback.
  • Include tests in code reviews to ensure adherence to standards.
  1. We want to know you better: Which main Code Editor/IDE you are using, and what makes it your preferred choice? Additionally, could you share the plugins/extensions you use with it, explaining their significance in enhancing your coding experience?

My preferred code editor/IDE is Visual Studio Code (VS Code). I really don't have any core reason why I use it but it has an extensive plugin ecosystem, and user-friendly interface. I recently used sublime text but i guess I just didn't get the feel like i get from using VS Code

Most of the plugins I use are:

PHPUnit: For PHP unit testing, PHPUnit ensures that my code functions as expected, helping me catch bugs early in the development process.

ESLint and Prettier: I love this. These plugins enforce JavaScript code quality and formatting standards, and ensure consistency and readability across my projects.

PHPCS: PHP CodeSniffer (PHPCS) is enforces PHP coding standards, helping me maintain code quality and adhere to best practices.

PHP Debug: This extension provides debugging support for PHP code, allowing me to troubleshoot and resolve issues efficiently.

Figma for VS Code: Integrating Figma with VS Code streamlines my workflow by allowing me to preview and inspect Figma designs directly within my editor.

GitLens: GitLens enhances the built-in Git capabilities of VS Code, providing features such as commit history exploration, and code lens integration.It helps in control and collaboration.

Remote - SSH: This extension enables me to work with remote development environments over SSH directly from VS Code.

Live Share: I use Live Share for real-time collaborative editing and debugging within VS Code, to collaborate with team members.

  • Yes i do utilize AI tools to enhance my daily workflow. Here are the ones I use

Github Co-pilot: I use github co-pilot because it boosts my productivity, enhances code quality and helps in learning more.

Google PageSpeed: I use this to test the speed of my page as it elps me to analyze website performance and user experience.

Chat GPT: This also helps with improving my code quality, learning not only for coding but for other information i might need.

CODING SECTION

<?php
/*
 * Plugin Name: Custom Table
 * Description: This plugin provides functionality for updating, deleting, inputting, and displaying data in a custom table. It also includes search functionality.
 * Version: 1.0.0
 * Requires at least: 5.0
 * Requires PHP: 7.0
 * Author: Odi Pearl
 * Author URI: https://pearlportfolio.netlify.app/
 * License: GPL-2.0+
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Update URI:
 * Text Domain: custom-things-form
 * Domain Path:
 */


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

class CustomThingsForm {
  public function __construct() {
      $this->conn = new mysqli("localhost", "root", "", "wordpress");

      // Check connection
      if ($this->conn->connect_error) {
          die("Database connection failed: " . $this->conn->connect_error);
      }

      // Register hooks
      add_action('init', array($this, 'create_custom_post_type'));
      add_action('wp_enqueue_scripts', array($this, 'load_assets'));
      add_shortcode('custom-form', array($this, 'my_shortcode_form'));
      add_action('wp_footer', array($this, 'load_script'));
      add_action('rest_api_init', array($this, 'register_rest_api'));
      add_action('wp_ajax_custom_edit_entry', array($this, 'handle_edit_entry'));
      add_action('wp_ajax_custom_delete_entry', array($this, 'handle_delete_entry'));
      add_shortcode('display-database-data', array($this, 'display_database_data_shortcode'));
  }

  public function create_custom_post_type() {
      $args = array(
          'public' => true,
          'has_archive' => true,
          'supports' => array('title', 'editor'),
          'exclude_from_search' => true,
          'publicly_queryable' => false,
          'capabilities' => array('manage options'),
          'labels' => array(
              'name' => 'Custom Form',
              'singular_name' => 'Custom Form Entry'
          ),
          'menu_icon' => 'dashicons-media-text',
      );

      register_post_type('custom_things_form', $args);
  }

  public function load_assets() {
      wp_enqueue_script(
          'custom-things-form-script',
          plugins_url('js/script.js', __FILE__),
          array('jquery'),
          '1.0.0',
          true
      );
  }

  public function my_shortcode_form() {
      ?>
      <h1>Please fill the form below</h1>
      <form id="custom-things-form__form">
          <input name="name" type="text" placeholder="Thing's name">
          <button type="submit">Send</button>
      </form>
      <?php
  }

  public function load_script() {
      ?>
      <script>
          var nonce = '<?php echo wp_create_nonce('wp_rest'); ?>';
          var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>'; // AJAX URL
          (function($){
              $('#custom-things-form__form').submit(function(event){
                  event.preventDefault();
                  var form = $(this).serialize();

                  $.ajax({
                      method: 'post',
                      url: '<?php echo esc_url_raw(get_rest_url(null, 'custom-things-form/v1/insert-things')); ?>',
                      headers: {'X-WP-Nonce' : nonce },
                      data: form,
                      success: function(response) {
                          alert('Form submitted successfully!');
                          updateTable(response.entry_id, response.name);
                      },
                      error: function(xhr, status, error) {
                          alert('Form submission failed. Please try again later.');
                      }
                  });
              });

              function updateTable(id, name) {
                  var newRow = '<tr>' +
                      '<td>' + id + '</td>' +
                      '<td class="editable" contenteditable="false">' + name + '</td>' +
                      '<td>' +
                      '<button class="edit-button">Edit</button>' +
                      '<button class="save-button" style="display:none;">Save</button>' +
                      '<button class="delete-button">Delete</button>' +
                      '</td>' +
                      '</tr>';

                  $('#database-table tbody').append(newRow);
              }
          })(jQuery);
      </script>
      <?php
  }

  public function register_rest_api()
    {
        //Endpoint for inserting data
        $namespace = 'custom-things-form/v1';
        register_rest_route($namespace, '/insert-things', array(
            'methods' => 'POST',
            'callback' => array($this, 'insert_data_to_my_table'),
            'permission_callback' => '__return_true',
        ));

        //Endpoint for editing data
        register_rest_route($namespace, '/save-changes', array(
            'methods' => 'POST',
            'callback' => array($this, 'save_changes'),
            'permission_callback' => '__return_true',
        ));

        //Endpoint for deleting data
        register_rest_route($namespace, '/delete-entry', array(
            'methods' => 'POST',
            'callback' => array($this, 'handle_delete_entry'),
            'permission_callback' => '__return_true',
        ));
    }



  public function insert_data_to_my_table($data) {
      $response_data = array();

      $nonce = $data->get_header('X-WP-Nonce');
      if (!wp_verify_nonce($nonce, 'wp_rest')) {
          $response_data = new WP_Error('invalid_nonce', 'Invalid nonce', array('status' => 403));
      } else {
          $params = $data->get_params();
          $name = sanitize_text_field($params['name']);

          if ($this->conn->connect_error) {
              $response_data = new WP_Error('db_error', 'Database connection failed', array('status' => 500));
          } else {
              $sql = "INSERT INTO things (name) VALUES ('$name')";

              if ($this->conn->query($sql) === true) {
                  $entry_id = $this->conn->insert_id;
                  $response_data = rest_ensure_response(array('message' => 'Form data inserted successfully', 'entry_id' => $entry_id, 'name' => $name));
              } else {
                  $response_data = new WP_Error('insert_error', 'Error inserting data', array('status' => 500));
              }
          }
      }
      $this->conn->close();
      return $response_data;
  }

    public function save_changes($data) {
        // Extract data from the request
        $id = $data['id'];
        $name = $data['name'];

        // Sanitize data
        $id = intval($id);
        $name = $this->conn->real_escape_string($name); // Escape the input to prevent SQL injection

        // Update data in the database
        $sql = "UPDATE things SET name = '$name' WHERE id = $id";

        if ($this->conn->query($sql) === true) {
            return rest_ensure_response(array('message' => 'Changes saved successfully'));
        } else {
            return new WP_Error('update_error', 'Error updating data: ' . $this->conn->error, array('status' => 500));
        }
    }
    public function handle_edit_entry() {
      // Verify nonce
      check_ajax_referer('custom_edit_entry_nonce', 'nonce');

      // Get the data from the AJAX request
      $id   = isset($_POST['id']) ? intval($_POST['id']) : 0;
      $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : '';

      // Update the database using $wpdb
      global $wpdb;
      $table_name = $wpdb->prefix . 'db';

      $updated = $wpdb->update(
          $table_name,
          array('name' => $name),
          array('id' => $id),
          array('%s'), // Data format
          array('%d')  // Where format
      );

      if ($updated !== false) {
          wp_send_json_success('Entry updated successfully');
      } else {
          wp_send_json_error('Error updating data: ' . $wpdb->last_error);
      }
  }

  public function handle_delete_entry() {
      // Verify nonce
      check_ajax_referer('custom_delete_entry_nonce', 'nonce');
      $id = isset($_POST['id']) ? intval($_POST['id']) : 0;

      global $wpdb;
      $table_name = $wpdb->prefix . 'db'; 

      $deleted = $wpdb->delete(
          $table_name,
          array('id' => $id),
          array('%d') // Where format
      );

      if ($deleted !== false) {
          wp_send_json_success('Entry deleted successfully');
      } else {
          wp_send_json_error('Error deleting entry: ' . $wpdb->last_error);
      }
  }


    // Method to fetch data from the database
    public function my_shortcode_list() {
        global $wpdb;
        $data = $wpdb->get_results("SELECT * FROM things", ARRAY_A);
        return $data;
    }
    public function display_database_data() {
        $data = $this->my_shortcode_list();

        if (empty($data)) {
            return '<p>No data available.</p>';
        }
        $output = '<input type="text" id="search-input" placeholder="Search">';
        $output .= '<table id="database-table">';
        $output .= '<thead><tr><th>ID</th><th>Thing Name</th><th>Actions</th></tr></thead>';
        $output .= '<tbody>';
        foreach ($data as $entry) {
            $output .= '<tr>';
            $output .= '<td>' . esc_html($entry['id']) . '</td>'; 
            $output .= '<td class="editable">' . esc_html($entry['name']) . '</td>'; 
            $output .= '<td>
                          <button class="edit-button">Edit</button>
                          <button class="save-button" style="display:none;">Save</button>
                          <button class="delete-button">Delete</button>
                        </td>';
            $output .= '</tr>';
        }
        $output .= '</tbody>';
        $output .= '</table>';

        // Add JavaScript for search and edit and delete functionality
        $output .= '<script>
                      (function($) {
                          $(document).ready(function() {
                              $("#search-input").on("keyup", function() {
                                  var value = $(this).val().toLowerCase();
                                  $("#database-table tbody tr").filter(function() {
                                      $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
                                  });
                              });

                              $(".edit-button").on("click", function() {
                                  var $row = $(this).closest("tr");
                                  $row.find(".editable").attr("contenteditable", "true").focus();
                                  $row.find(".edit-button").hide();
                                  $row.find(".save-button").show();
                              });

                              $(".save-button").on("click", function() {
                                  var $row = $(this).closest("tr");
                                  var id = $row.find("td:first").text();
                                  var name = $row.find(".editable").text();

                                  // AJAX call to handle edit entry
                                  $.ajax({
                                      url: ajaxurl,
                                      type: "POST",
                                      data: {
                                          action: "custom_edit_entry",
                                          nonce: "'. wp_create_nonce( 'custom_edit_entry_nonce' ) .'",
                                          id: id,
                                          name: name
                                      },
                                      success: function(response) {
                                          alert("Changes saved successfully!");
                                          $row.find(".editable").attr("contenteditable", "false");
                                          $row.find(".edit-button").show();
                                          $row.find(".save-button").hide();
                                      },
                                      error: function(xhr, status, error) {
                                          alert("Failed to save changes. Please try again later.");
                                      }
                                  });
                              });

                              $(".delete-button").on("click", function() {
                                  var $row = $(this).closest("tr");
                                  var id = $row.find("td:first").text();

                                  // AJAX call to handle delete entry
                                  if (confirm("Are you sure you want to delete this entry?")) {
                                      $.ajax({
                                          url: ajaxurl,
                                          type: "POST",
                                          data: {
                                              action: "custom_delete_entry",
                                              nonce: "'. wp_create_nonce( 'custom_delete_entry_nonce' ) .'",
                                              id: id
                                          },
                                          success: function(response) {
                                              alert("Entry deleted successfully!");
                                              $row.remove();
                                          },
                                          error: function(xhr, status, error) {
                                              alert("Failed to delete entry. Please try again later.");
                                          }
                                      });
                                  }
                              });
                          });
                      })(jQuery);
                  </script>';

        return $output;

    }
    // Shortcode to display database data on a page
    public function display_database_data_shortcode() {
        return $this->display_database_data();
    }
}
new CustomThingsForm();
?>

Enter fullscreen mode Exit fullscreen mode

Top comments (0)