How To Make a WordPress Plugin Tutorial

Wordpress Plugin Development
Share:

About

Some time ago I had to make a WordPress plugin as part of my job. Here I will document what I have learned in the process. Hopefully, this can also be useful to anyone who wants to make their own plugin or do any other WordPress development. 

In this post, we will make a plugin while at the same time learning how to use some of the WordPress APIs. There are plenty more things to learn about which will not be covered here, for example, custom taxonomies, making themes, editor blocks, … If you are interested in that you can check out the official WordPress developer resources here.  

Note: To follow this tutorial some existing knowledge of PHPJS, CSS and HTML is required. The full source code of the finished plugin made in this tutorial can be found here.
Here is a list of the covered topics:

Making a Basic Plugin

First make a folder and name it the same you will name your plugin. Next put in a .php file and also named it like your plugin, in my case MyPlugin.php. For WordPress to recognize this as a plugin you need to need to put the following into the file:
<?php
/**
 * Plugin Name: My Plugin
 * Plugin URI: https://eecs.blog/
 * Description: This plugin was created as part of a series of tutorials on how to make a WordPress plugin.
 * Version: 1.0.0
 * Author: Tsla
 * Author URI: https://eecs.blog/
 * License: GPL2
 */

//Prevents direct access to the file for security reasons.
if(!defined('ABSPATH'))
    die;
For now, I will just drag and drop the plugin folder into the plugins folder(/wordpress/wp-content/plugins) in the WordPress installation location. (I’m running it locally on my computer for development purposes.)  
Note: Otherwise, you can just zip up your plugin folder and upload it on the plugins page in the WordPress admin backend.
Now go to the Plugins page in your WordPress admin area and you should see your plugin popup in the list. The information like name, description, author, version, … is getting pulled from the text we defined in the MyPlugin.php file. You can of course change this to whatever you want.
wordpres plugin minimum code

Install, Uninstall and Activation Hook

When you activate, deactivate or uninstall a plugin WordPress will “fire” a hook. We can bind functions to these hooks and run some specific code required to activate, deactivate or uninstall our plugin.

In the code below I will create a class to represent the plugin. Inside it, I will put the required functions and register them with the  register_activation_hook()

The register() will be used later to include any JS, CSS or PHP files. This isn’t a hook. Just a function that we’ll call when the plugin is about to be used.

<?php
/**
 * Plugin Name: My Plugin
 * Plugin URI: https://eecs.blog/
 * Description: This plugin was created as part of a series of tutorials on how to make a WordPress plugin.
 * Version: 1.0.0
 * Author: Tsla
 * Author URI: https://eecs.blog/
 * License: GPL2
 */

//Prevents direct access to the file for security reasons.
if(!defined('ABSPATH'))
    die;

class MyPlugin{
    function __construct(){
        //The constructor runs when the class is initialized.
    }

    function register(){
        //This is where we will later register/include any js, css or php files we require.
    }

    function activate(){
        //Remove rewrite rules and then recreate rewrite rules.
        flush_rewrite_rules();

        //When the user clicks "activate" this code will run.

        //Stuff to initially set up your plugin would be added here. 
        //Like for example, making a table in the database to store your plugins data.

        //We will add it later.
    }

    function deactivate(){
        //Remove rewrite rules and then recreate rewrite rules.
        flush_rewrite_rules();

        //When the user clicks "deactivate" this code will run.

        //Code to deactivate the plugin would be added here. 
        //Like for example, disable.

        //We will add it later.
    }

    function uninstall(){
        //When the user clicks "uninstall" this code will run.

        //Code to delete the plugin and clean up after it would be added here.
        //Like for example, deleting a table in the database that was used to store your plugins data.

        //We will add it later.
    }
}

//Create a new instance of the plugin class.
$myPlugin = new MyPlugin();
//Call the register function.
$myPlugin->register();

//Register the activation hook.
register_activation_hook(__FILE__, array($myPlugin, 'activate')); 
//Register the deactivation hook.
register_deactivation_hook(__FILE__, array($myPlugin, 'deactivate')); 
//Register the uninstall hook.
register_uninstall_hook(__FILE__, array($myPlugin, 'uninstall')); 
We will implement the functionality for these functions later when some actual logic is added and we have something to initialize/delete.

Adding a Short Code

Shortcodes allow us to call and pass parameters to our plugins from the WordPress pages/posts. To demonstrate this I’ll make the plugin take in a value and return some text depending on the input.
<?php
/**
 * Plugin Name: My Plugin
 * Plugin URI: https://eecs.blog/
 * Description: This plugin was created as part of a series of tutorials on how to make a WordPress plugin.
 * Version: 1.0.0
 * Author: Tsla
 * Author URI: https://eecs.blog/
 * License: GPL2
 */

//Prevents direct access to the file for security reasons.
if(!defined('ABSPATH'))
    die;

class MyPlugin{
    function __construct(){
        //The constructor runs when the class is initialized.
    }

    function register(){
        //Add/register shortcode. 
        add_shortcode( 'MyPlugin', array( $this, 'shortCode' ));
    }

    function activate(){
        //Remove rewrite rules and then recreate rewrite rules.
        flush_rewrite_rules();

        //When the user clicks "activate" this code will run.

        //Stuff to initially set up your plugin would be added here. 
        //Like for example, making a table in the database to store your plugins data.

        //We will add it later.
    }

    function deactivate(){
        //Remove rewrite rules and then recreate rewrite rules.
        flush_rewrite_rules();

        //When the user clicks "deactivate" this code will run.

        //Code to deactivate the plugin would be added here. 
        //Like for example, disable.

        //We will add it later.
    }

    function uninstall(){
        //When the user clicks "uninstall" this code will run.

        //Code to delete the plugin and clean up after it would be added here.
        //Like for example, deleting a table in the database that was used to store your plugins data.

        //We will add it later.
    }

    function shortCode($attributes = []){
        //Get the attribute from short code.
        $attributeValue = strtolower($attributes['display']);

        $HTML = "";

        if($attributeValue == "greeting"){
            $HTML = "
                <div>
                    <h3>Hello World.</h3>
                </div>
            ";
        }else{
            $HTML = "
                <div>
                    <h3>Just some random text.</h3>
                </div>
            ";
        }

        //Return html to the spot the short code was placed.
        return $HTML;
    }
}

//Create a new instance of the plugin class.
$myPlugin = new MyPlugin();
//Call the register function.
$myPlugin->register();

//Register the activation hook.
register_activation_hook(__FILE__, array($myPlugin, 'activate')); 
//Register the deactivation hook.
register_deactivation_hook(__FILE__, array($myPlugin, 'deactivate')); 
//Register the uninstall hook.
register_uninstall_hook(__FILE__, array($myPlugin, 'uninstall')); 
Here you can see the result. When we put “greeting” as the parameter in the shortcode we get a “Hello World.” on the page else some other text gets displayed.

Adding CSS, PHP and JS Files

For this example and from now on, I will be making a simple message board plugin. I will be using this simple project to demonstrate how to develop further plugin functionality. 

For this example, we’ll be adding:
  • A PHP file that is going to contain a class called MesageBoard this class will have a function called getBoard() which will return the HTML required to create the message board.
  • A CSS file that will contain some basic styling for our message board.
  • A Javascript file that will contain the code to make the message board work. I will be using the jQuery library in my code so it will have to be enqueued just like our Javascript file.

PHP:

This is a separate PHP file for the Messageboard. This file will have to be referenced in the main plugin file(MyPlugin.php) so it can be used.
MessageBoard.php
<?php
class MessageBoard{
    function getBoard(){
        return "
            <div id='wrapperDiv'>
                <div id='boardWrapper'>
                    <h3>Message board</h3>
                    <ul id='messageList'>
                    </ul>
                </div>
                <div id='messageWrapper'>
                    <h4>Enter a message.</h4>
                    <input type='text' id='messageBox'/>
                    <input type='button' id='button' value='Submit'>
                </div>
            </div>
        ";
    }
}

CSS:

Just some basic styling for the message board.
MessageBoard.css
#button{
    background-color: grey;
}

#messageBox{
    width: 300px;
    height: 40px;
}

#button{
    width: 80px;
    padding: 0px;
    height: 40px;
}

#messageList{
    border: 1px black solid;
    min-height: 100px;
    width: 400px;
    list-style-type: none;
}

JS:

Simple javascript code that puts the text from the textbox into the list(message board).
window.onload=function(){
    //Register event.
    buttonClickEvent()
}

function buttonClickEvent(){
    jQuery("[id='button']").click(function(event){
        const message = jQuery("[id='messageBox']").val();
        jQuery("[id='messageList']").append("<li>"+ message +"</li>");
    });
}
Now we need to reference/enqueue the files. To reference the PHP file we can use the require_once() function and pass it the path of the PHP file.
For the CSS the wp_enqueue_style() function will be used. The first parameter must be a unique name you choose for the style sheet. The second parameter is the path to the file.
And for the javascript the wp_enqueue_script() function will be used. The first parameter must be a unique name you choose for the script. The second parameter is the path to the file.
MyPlugin.php
<?php
/**
 * Plugin Name: My Plugin
 * Plugin URI: https://eecs.blog/
 * Description: This plugin was created as part of a series of tutorials on how to make a WordPress plugin.
 * Version: 1.0.0
 * Author: Tsla
 * Author URI: https://eecs.blog/
 * License: GPL2
 */

//Prevents direct access to the file for security reasons.
if(!defined('ABSPATH'))
    die;

class MyPlugin{
    function __construct(){
        //The constructor runs when the class is initialized.
    }

    function register(){
        //Add/register shortcode. 
        add_shortcode( 'MyPlugin', array( $this, 'shortCode' ));

        //Reference .php files. 
        require_once(dirname(__FILE__) .'\MessageBoard.php'); //__FILE__ gets the current file, dirname() gets the parent directory 

        $file = __FILE__;
        $fileDir = dirname(__FILE__);
        $fileDir2 = dirname(dirname(__FILE__));

        //Enqueue styles. plugins_url() gets the plugin directory
        wp_enqueue_style('MessageBoard', plugins_url('/MyPlugin/MessageBoard.css'));

        //Enqueue
        wp_enqueue_script('jQuery_js', plugins_url('/MyPlugin/jquery-3.5.1.min.js'));
        wp_enqueue_script('MessageBoard_js', plugins_url('/MyPlugin/MessageBoard.js'));
    }

    function activate(){
        //Remove rewrite rules and then recreate rewrite rules.
        flush_rewrite_rules();

        //When the user clicks "activate" this code will run.

        //Stuff to initially set up your plugin would be added here. 
        //Like for example, making a table in the database to store your plugins data.

        //We will add it later.
    }

    function deactivate(){
        //Remove rewrite rules and then recreate rewrite rules.
        flush_rewrite_rules();

        //When the user clicks "deactivate" this code will run.

        //Code to deactivate the plugin would be added here. 
        //Like for example, disable.

        //We will add it later.
    }

    function uninstall(){
        //When the user clicks "uninstall" this code will run.

        //Code to delete the plugin and clean up after it would be added here.
        //Like for example, deleting a table in the database that was used to store your plugins data.

        //We will add it later.
    }

    function shortCode($attributes = []){
        //Get the attribute from short code.
        $attributeValue = strtolower($attributes['display']);

        $HTML = "";

        if($attributeValue == "board"){
            $messageBoard = new MessageBoard();
            $HTML = $messageBoard->getBoard();
        }else if($attributeValue == "greeting"){
            $HTML = "
                <div>
                    <h3>Hello World.</h3>
                </div>
            ";
        }else{
            $HTML = "
                <div>
                    <h3>Just some random text.</h3>
                </div>
            ";
        }

        //Return html to the spot the shortcode was placed.
        return $HTML;
    }
}

//Create a new instance of the plugin class.
$myPlugin = new MyPlugin();
//Call the register function.
$myPlugin->register();

//Register the activation hook.
register_activation_hook(__FILE__, array($myPlugin, 'activate')); 
//Register the deactivation hook.
register_deactivation_hook(__FILE__, array($myPlugin, 'deactivate')); 
//Register the uninstall hook.
register_uninstall_hook(__FILE__, array($myPlugin, 'uninstall')); 
As you can see the message board appears and it works as expected.
The files we included should be included as part of your webpage when it gets loaded. You can see them if you(.php files are only on the server of course):
open the chrome developer tools(press F12) > go to sources > open up the WordPress directory > open plugins > open your plugin directory
Note: PHP dirname(__FILE__)
__FILE__ will return the path of the current PHP file. The direname() function will return the parent directory path of the directory path that was passed in as a parameter.
The plugins_url() function can also be used to get the path for the plugins folder.

Front-end Back-end Communication With AJAX

As it stands right now the message board can be written to but the results don’t gat saved anywhere. To change this we need to save the message board contents to the WordPress database. However we first need to get the data from the front-end to the back-end.

We can do this by using AJAX(asynchronous Javascript and XML). We’ll use JSON instead of XML. Regularly when you use the AJAX approach to communicate between the front/back-end you would just send the data to the PHP file(located on your server) that contains your back-end code. But with WordPress, you should instead send all of your requests to the admin-ajax.php file. Then you have to enqueue the PHP function you want to execute(upon receiving the request) with a unique name. Finally, you need to include this name in the request sent from the front-end.   

Let’s see exactly how this is done below. Any further explanations are provided as comments within the code.

Note: In this section, I will only demonstrate how to send/receive data using AJAX. I will demonstrate how to store/retrieve data from the database in a later section.

JS:

MessageBoard.js
window.onload=function(){
    //Register event.
    buttonClickEvent()
}

function buttonClickEvent(){
    jQuery("[id='button']").click(function(event){
        const message = jQuery("[id='messageBox']").val();
        jQuery("[id='messageList']").append("<li>"+ message +"</li>");

        const messageBoardContents = jQuery("[id='messageList']").prop("outerHTML");
        saveMBContentsToDB(messageBoardContents);
    });
}

function saveMBContentsToDB(content){
    //Making an AJAX request using jQuery.
    jQuery.ajax({
        url: wp_ajax.ajax_url, //Give the url of the backend. wp_ajax was included into this JS file from the backend using wp_localize_script() function.
        type: 'post', //Set request type to POST                                          
        dataType: 'text', //Set type to text.         
        data: {
          action:'save', //Name under which the function was registered in the backend.
          contentToSave:content, //Putting the value of the "content" input parameter to the "contentToSave" property of the "data" object.                                            
        },
        success: function (data){ //After the backend code is done executing the frontend will continue from here. Any data sent from the backend will be available in the data parameter.
            saveMBContentsToDBCallback(data); //Instead of executing the code in this anonymous function we'll forward it to callback function.
        },
        error: function(errorThrown){ //This will handle any errors if they occour.
          console.log("This has thrown an error:" + errorThrown);
        }                     
    });           
}

function saveMBContentsToDBCallback(data){
    const dataObject = JSON.parse(data); //Deserialize the received json data.
    console.log(dataObject.message); //Log the message from the backend.
}

PHP:

MessageBoard.php
//Save // add_action("wp_ajax_"+"action property contents", "function to be called");
add_action('wp_ajax_save', 'save'); //For logged in users.
add_action('wp_ajax_nopriv_save', 'save'); //For not logged in users.      

function save(){
    //All the properties that were sent via POST request can be accessed from the $_POST[] array.
    $inputData = $_POST['contentToSave']; 

    //Implement code to save data to the database ...

    //Make an array with a message, serialize it to json and return 
    echo json_encode(["message" => "The content was saved."]);

    die; //Terminate php execution.
}
The PHP WordPress backend has received the AJAX request from the frontend. The function we registered before has fired and as you can see the sent data was successfully received.
After the response is received from the backend the callback function will be called. The code execution in the front end will continue from thereon.
The callback function has completed its execution and the message that was returned from the backend was finally printed in the console.

Database Access

In this section, we’ll learn how to access the database and read/write/create tables in it. WordPress uses a MySQL database so obviously, all the queries will be written in the  MySQL syntax. 

In the previous section, we’ve seen how to get data from the frontend to the backend(and back to the frontend again). Now let’s see how to save this data into the database.

Note: I will create the table for storing the data manually in phpMyAdmin for this demonstration. In the later section Install, Uninstall Hooks (Continued) I will show how to make the table when the plugin is activated and delete it when the plugin is uninstalled. 

WP Databse Functions Demo

This code snippet has a few examples of how to use the database manipulation functions included by WordPress. For more info. check out the official wp documentation.
//This function can be used to execute any MySQL statment: 
    //query("your SQL query statement");
    $users = $wpdb->query("SELECT * FROM users");


    //Prevents SQL injection.
    //prepare("your SQL query statement", "array with the values"); //% represents the parameter (%s for string; %d for integer, %f for float)
    $unsanitizedString = "bob";
    $user = $wpdb->query($wpdb->prepare("SELECT * FROM users WHERE name LIKE %s", [$unsanitizedString]));


    //Inserts new data:    
    //insert("table name", "your data as an associative array");
    $wpdb->insert( 
        "users", 
        [ "id" => 1, "name" => "bob" ], //column => value 
        [ "%d", "%s"] //format (%s for string; %d for integer, %f for float)
    );


    //Gets a single variable: 
    //get_var("your SQL query statement");
    $userName = $wpdb->get_var("SELECT name FROM users WHERE id LIKE 1");


    //Gets multiple results and returns associative array.
    //get_results("your SQL query statement", output_type ); //output_type how you get the reults indexed array = ARRAY_N, associative array = ARRAY_A, object = OBJECT
    $allUsers = $wpdb->get_results("SELECT name FROM users", ARRAY_A); 


    //Updates table: 
    //update("table name", "your data as an associative array", "where condition as an associative array");
    $wpdb->update(
        "users",
        ["name" => "alice"],
        ["name" => "bob"]
    );


    //Deletes table row: 
    //delete("table name", "where condition as an associative array");
    $wpdb->delete("users", ['id' => 1]);

    //You can get all the available functions and examples in the official WordPress documentation here: 
    //https://developer.wordpress.org/reference/classes/wpdb/

Creating The Table

As mentioned before I will create the table in the DB manually for this demonstration. I will use phpmyadmin to connect to the database and add in a table called message_board.
Then I will add one column called content of type TEXT for the mesage board contents and one ID column of type INT.
I will insert some initial data into the table so we can later update it.

Saving To And Querying The Database

I will update the code from the previous AJAX example. The saving functionality will be implemented and the load function will be added to query the DB.

JS:

MessageBoard.js
window.onload=function(){
    //Register event.
    buttonClickEvent();
    //Load existing messages onto the message board.
    loadMesssageBoard();
}

function buttonClickEvent(){
    jQuery("[id='button']").click(function(event){
        const message = jQuery("[id='messageBox']").val();
        jQuery("[id='messageList']").append("
  • "+ message +"
  • "); const messageBoardContents = jQuery("[id='messageList']").prop("innerHTML"); saveMBContentsToDB(messageBoardContents); }); } //Load messagess////////////////////////////////////////////////////////////////////// function loadMesssageBoard(){ //Making an AJAX request using jQuery. jQuery.ajax({ url: wp_ajax.ajax_url, //Give the url of the backend. wp_ajax was included into this JS file from the backend using wp_localize_script() function. type: 'post', //Set request type to POST dataType: 'text', //Set type to text. data: { action:'load', //Name under which the function was registered in the backend. }, success: function (data){ //After the backend code is done executing the frontend will continue from here. Any data sent from the backend will be available in the data parameter. loadMesssageBoardCallback(data); //Instead of executing the code in this anonymous function we'll forward it to callback function. }, error: function(errorThrown){ //This will handle any errors if they occour. console.log("This has thrown an error:" + errorThrown); } }); } function loadMesssageBoardCallback(data){ const dataObject = JSON.parse(data); //Deserialize the received json data. jQuery("[id='messageList']").html(dataObject); } /////////////////////////////////////////////////////////////////////////////////////// //Save messages//////////////////////////////////////////////////////////////////////// function saveMBContentsToDB(content){ //Making an AJAX request using jQuery. jQuery.ajax({ url: wp_ajax.ajax_url, //Give the url of the backend. wp_ajax was included into this JS file from the backend using wp_localize_script() function. type: 'post', //Set request type to POST dataType: 'text', //Set type to text. data: { action:'save', //Name under which the function was registered in the backend. contentToSave:content, //Putting the value of the "content" input parameter to the "contentToSave" property of the "data" object. }, success: function (data){ //After the backend code is done executing the frontend will continue from here. Any data sent from the backend will be available in the data parameter. saveMBContentsToDBCallback(data); //Instead of executing the code in this anonymous function we'll forward it to callback function. }, error: function(errorThrown){ //This will handle any errors if they occour. console.log("This has thrown an error:" + errorThrown); } }); } function saveMBContentsToDBCallback(data){ const dataObject = JSON.parse(data); //Deserialize the received json data. console.log(dataObject.message); //Log the message from the backend. } ///////////////////////////////////////////////////////////////////////////////////////

    PHP:

    MessageBoard.php
    //Save // add_action("wp_ajax_"+"action property contents", "function to be called");
    add_action('wp_ajax_save', 'save'); //For logged in users.
    add_action('wp_ajax_nopriv_save', 'save'); //For not logged in users.      
    //Load
    add_action('wp_ajax_load', 'load');
    add_action('wp_ajax_nopriv_load', 'load');   
    
    function save(){
        //Storing the actual HTML in the DB is not the best idea. Ideally, it should be serialized then stored in the DB. This is just quicker and easier for the demonstration.
        //Here I will use urlencode() to mitigate SQL injection. Usually, you would use the strip_tags() function, but in this case it would ruin our HTML. Or use the prepare() function provided by WP. 
    
        //All the properties that were sent via POST request can be accessed from the $_POST[] array.
        $inputData = urlencode($_POST["contentToSave"]);
    
        //$wpdb is a global object that contains functions to work with the DB. It is instantiated and provided by wordpress automatically.
        //So this is all we have to do to use it: 
        global $wpdb; //Get the global instance of the wpdb class(used to work with the DB).     
        //Run update query.
        $wpdb->query("UPDATE message_board SET content = '" . $inputData . "' WHERE id LIKE 1");
    
        //Make an array with a message, serialize it to json and return 
        echo json_encode(["message" => "The content was saved."]);
    
        die; //Terminate php execution.
    }
    
    function load(){
        //$wpdb is a global object that contains functions to work with the DB. It is instantiated and provided by wordpress automatically.
        //So this is all we have to do to use it: 
        global $wpdb; //Get the global instance of the wpdb class(used to work with the DB). 
        //Get stored messages.
        $content = $wpdb->get_var("SELECT content FROM message_board WHERE id LIKE 1");
        
        $content = urldecode($content);
    
        echo json_encode($content);
    
        die; //Terminate php execution.
    }

    Result:

    As you can see the message board now gets its text saved/loaded from the database.

    Working With Files

    We won’t be needing any of this in our plugin but I think knowing how to working with the file system is very useful so I added this code snippet anyway. It has a few examples of how to use the WordPress files API to work with files. For more info. check out the official wp documentation.
    function WP_Filesystem_Functions_Demo(){
        //Here I will demonstrate a few of the more common For the full list and full functionality of the WP filesystem functions check the official documentation.
        //https://developer.wordpress.org/reference/classes/wp_filesystem_direct/#methods
    
        //Call WP_Filesystem() or the $wp_filesystem global will be null;
        WP_Filesystem();
        //Get the file system object.
        global $wp_filesystem;
    
        //Here we'll just get the plugin folder path.///////////
        $path = dirname(__FILE__);
    
        $dirPath = $path . "/MyNewFolder";       //Define path/name for our new directory.
        $filepath = $dirPath . "MyNewFile.txt";  //Define path/name for our new file.
    
        ////////////////////////////////////////////////////////
    
    
        //Make a directory.
        $wp_filesystem->mkdir($dirPath);
    
        //Make a file.
        $wp_filesystem->put_contents($filepath, "Hello World!");
    
        //Get the data from the file.
        $fileContents = $wp_filesystem->get_contents($filepath);
    
        //Changes file/folder permissions.
        //chmod(file/folder path, permissions(same logic as linux permissions), recursive(optional) apply to all files/subfolders)
        $wp_filesystem->chmod($filepath, 777); //777 gives everyone all the permissions.
    
        //Copy file, with new name into the same directory.
        //copy(source, destination, overwrite the destination file if it exists(optional parameter))
        $wp_filesystem->copy($filepath, $path. "\MyNewestFile.txt");
    
        //Move the file file. 
        //move(source, destination, overwrite the destination file if it exists(optional parameter))
        $wp_filesystem->move($filepath, $path . "\MyNewFile.txt"); //This will move the file from MyNewFolder to the plugin root folder.
    
        //Check if the file exists...
        if($wp_filesystem->exists($path . "\MyNewFile.txt"))
            $wp_filesystem->delete($path . "\MyNewFile.txt"); //if so delete it.
    
        //Remove directory. 
        $wp_filesystem->rmdir($dirPath);
        //Delete all the files and subdirectories within the folder.
        //rmdir(path, recursive(optional))
        $wp_filesystem->rmdir($dirPath, true); 
    }

    Result:

    Install, Unistall Hooks (Continued)

    Now that we’ve seen how to work with the WordPress database and Files API in the previous sections let’s use that knowledge to finish up our hooks. 

    Activation Hook

    When the plugin is activated we will check if the “message_board” table is already present in the database. If it doesn’t exist we will create it and put some initial data in.

    MyPlugin.php
        function activate(){
            //Remove rewrite rules and then recreate rewrite rules.
            flush_rewrite_rules();
    
            //When the user clicks "activate" this code will run.
    
            //Stuff to initially set up your plugin would be added here. 
            //Like for example, making a table in the database to store your plugins data.
    
            global $wpdb; 
            
            //Check if table already exists. If not add it.
            if($wpdb->query("SHOW TABLES LIKE 'message_board'") == 0){
    
                //Create the message_board table.
                $wpdb->query('CREATE TABLE message_board
                    (
                        id INTEGER NOT NULL,
                        content TEXT,
                        PRIMARY KEY (id)
                    )'
                );
                
                //"Initialize" it with some data.
                $wpdb->insert( 
                    "message_board", 
                    array( 
                        'content' => "", 
                        'id' => 1
                    ) 
                );
            }
    
        }

    Unsinstall Hook

    Instead of using the uninstall hook we will create an uninstall.php file in the root plugin directory. The code inside it will be automatically run when the plugin is to be uninstalled.

    The code below will remove the table we created on the first activation. All the directories and files will be removed automatically, no code needed. 

    uninstall.php
    <?php
    
    //The code in this file will be run when the uninstall button for the plugin is clicked.
    //All that we have to do is make this uninstall.php file and it will be run automatically on uninstall.
    //No need to register any hook. 
    
    //Check if plugin is actually to be uninstalled...
    if (!defined('WP_UNINSTALL_PLUGIN'))
    	die; //.. if not finish program execution here.
    
    global $wpdb;      
    //Remove the "contents" table and all of its data from the WP database.
    $wpdb->query("DROP TABLE message_board");

    Admin Backend

    Finally, let’s see how to add an admin page so that we can configure the plugin from the WP admin area. In this case, I will just add a simple button that will allow you to clear the message board.
    We’ll make a file named AdminPage.php. This is where you define the layout of your Admin area page. I will only add one button that can be used to clear the message board if you are the administrator.
    AdminPage.php
    <?php
        echo "
                <h1>Hello World</h1> 
                <div id='clearBoardButton' style='background-color: darkseagreen; width: fit-content; padding: 5px;'>Clear Message Board</div>
                <div id='message'></div>
            ";
    ?>
    This is the javascript file that will be included when the admin page loads. There will only be one event handler that will wait for the “Clear Messageboard” button to be clicked. Then it will make a call to the backend and handle the response which will indicate whether the operation was successful or not.
    AdminArea.js
    //On page load....
    window.onload=function(){
        //Register event.
        jQuery("[id='clearBoardButton']").click(function(event){
            //Making an AJAX request using jQuery.
            jQuery.ajax({
                url: wp_ajax.ajax_url, //Give the url of the backend. wp_ajax was included into this JS file from the backend using wp_localize_script() function.
                type: 'post', //Set request type to POST                                          
                dataType: 'text', //Set type to text.         
                data: { action:'clear' }, //Name under which the function was registered in the backend.                                        
                success: function (data){ //After the backend code is done executing the frontend will continue from here. Any data sent from the backend will be available in the data parameter.
                    //Deserialize the json string into an object.
                    deserializedData = JSON.parse(data);
                    //Display message. 
                    jQuery("[id='message']").html(deserializedData.message);
                },
                error: function(errorThrown){ //This will handle any errors if they occour.
                    console.log("This has thrown an error:" + errorThrown);
                }                     
            });   
        });
    }
    Next, we’ll add the clear() function to the MessageBoard.php file. This function will be called from the front-end when the clear button is clicked. It will check if the current user is an administrator, if so it will clear the message board contents in the database. In the end, it will return a message telling the user whether the operation was successful or not.
    MessageBoard.php > clear()
    //Clear
    //Make this available only to logged in users.
    add_action('wp_ajax_clear', 'clear');
    
    function clear(){
        //Check if the user has admin privileges.
    
        //Get the current user data.
        $user = wp_get_current_user();
        //Take the $user->roles array and chekc if it contains the 'admin' role.
        if(!in_array( 'administrator', (array) $user->roles )){
            //If not, return a warning and stop the code execution.
            echo json_encode(["message" => "You need to be an Admin to clear the message board."]);
            die; //Terminate php execution.
        }
    
        //$wpdb is a global object that contains functions to work with the DB. It is instantiated and provided by wordpress automatically.
        //So this is all we have to do to use it: 
        global $wpdb; //Get the global instance of the wpdb class(used to work with the DB).     
        //Run update query.
        $wpdb->query("UPDATE message_board SET content = '' WHERE id LIKE 1");
    
        //Make an array with a message, serialize it to json and return 
        echo json_encode(["message" => "Message Board was cleared."]);
    
        die; //Terminate php execution.
    }
    Finally, we have to register the admin page with WordPress in the main plugin file(MyPlugin.php). We’ll add the following lines of code at the end of our register() function.
    MyPlugin.php > register()
            //Admin page in WP backend.
    
            //Add admin page. 'add_admin_page' is the name of the function that will be called to add the page.
            //The array($this, 'add_admin_page') is used to specify that we are calling the function from $this object.
            add_action('admin_menu', array($this, 'add_admin_page'));
    
            //Add link to admin page from plugin listing on the plugins page.
            add_filter("plugin_action_links_" . $this->pluginTitle, array($this, 'AdminPageLink')); 
    The code we have just added  into the register() function will call add_admin_page(). This function will then be used to add all the files required for the admin area like the CSS, JS, and PHP. The process of enqueueing these files is the same as before.
    Also, the plugin icon in the toolbar will be added here by the add_menu_page() function.
    MyPlugin.php > add_admin_page()
            require_once(dirname(__FILE__) .'\MessageBoard.php'); //__FILE__ gets the current file, dirname() gets the parent directory 
    
            //Add a page to the wordpress backend menu.
            
            //add_menu_page('page title', 'menu title in side bar', 'define roles', 'unique page ID slug(can be whatever)', 'function that is called to initialize page ', 'sets icon in sidebar', 'position in sidebar')
            //'define roles' will define which user can see the page https://wordpress.org/support/article/roles-and-capabilities/#manage_options
            //You can find a list of all the existing icons here: https://developer.wordpress.org/resource/dashicons/ or put a url to your custom icon
            add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'MyPlugin', array($this, 'LoadMyPluginAdminPage'), 'dashicons-testimonial', 110); 
    
            //Enqueue styles
            wp_enqueue_style('adminAreaStyleSheet', plugins_url('MyPlugin/adminAreaStyleSheet.css'));
            //Enqueue
            wp_enqueue_script('adminArea_js', plugins_url('MyPlugin/adminArea.js'), /*NULLdependencies such as jQuery*//* array('jquery'), true*/);
            //Localize
            wp_localize_script( 'adminArea_js', 'wp_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );  
    When this function is called by the code above it will add the AdminPage.php file we created in the beginning.
    MyPlugin.php > LoadMyPluginAdminPage()
        function LoadMyPluginAdminPage(){
            require_once dirname(__FILE__) .'\AdminPage.php';
        }
    When this function is called by the code above it will add a link in the plugin listing on the plugins page.
    MyPlugin.php > AdminPageLink()
        public function AdminPageLink($links){
            //$links is a array of links that are present in the plugin listing on the plugins page.
            //To add a new link lets simply push a new HTML link into this array. 
            array_push($links, '<a href="admin.php?page=MyPlugin">Settings</a>');
    
            return $links;
        }

    Resulting Plugin Admin Page

    Share:

    Leave a Reply

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

    The following GDPR rules must be read and accepted:
    This form collects your name, email and content so that we can keep track of the comments placed on the website. For more info check our privacy policy where you will get more info on where, how and why we store your data.

    Advertisment ad adsense adlogger