Select Page
Deploying WordPress Plugins from GitHub to SVN Using GitHub Actions

Deploying WordPress Plugins from GitHub to SVN Using GitHub Actions

This blog post will guide you through setting up an automated workflow to deploy your WordPress plugin to the official WordPress plugin SVN repository directly from GitHub. Using GitHub Actions, you can streamline the release process every time a new tag is pushed to your GitHub repository. Let’s create a build-and-deploy-to-svn.yml file inside your Github repository/.github/workflows directory. Now, let’s follow the following steps:

1. Naming the Workflow

name: Build and Deploy to SVN

This defines the name of the workflow. It will appear under this title in the GitHub Actions tab, making it easy to identify the deployment workflow among others.

2. Triggering the Workflow on Tag Push

on:
  push:
    tag:
    - "*"

This section specifies that the workflow will be triggered whenever a new Git tag is pushed to the repository. The - "*" part means the workflow will run on any tag, no matter the version or format. This is useful when you want to deploy a specific version of your plugin (e.g., v1.0.0) to the WordPress SVN.

3. Defining the Job

jobs:
  build:
    runs-on: ubuntu-latest

Here, we define a job called build, which runs on the latest Ubuntu environment provided by GitHub. This is the virtual machine where all subsequent steps will be executed.

4. Checkout Repository

steps:
  - name: Checkout repository
    uses: actions/checkout@v4

This step checks out your GitHub repository so that the workflow can access the code. The actions/checkout@v4 action is a standard utility to fetch the repository’s content.

5. Set up Node.js

- name: Set up Node.js
  uses: actions/setup-node@v2
  with:
    node-version: '16.17.0'

In this step, Node.js is installed on the virtual machine. The version 16.17.0 is specified here (use whatever version you need), ensuring compatibility with the plugin’s build tools. This is important if your plugin uses Node.js-based tooling like Webpack or Gulp for compiling assets.

6. Install Plugin Dependencies

- name: Install dependencies
  run: npm install

This command installs the required npm dependencies for building your plugin. The --legacy-peer-deps flag is used to bypass potential issues with peer dependencies, which can occur with newer versions of npm.

7. Install Composer

- name: Install Composer
  run: sudo apt-get update && sudo apt-get install -y composer

WordPress development often relies on PHP packages, which are managed by Composer. This step installs Composer, making it available for use in the plugin’s build process.

8. Install WP-CLI

- name: Install WP CLI
  run: |
    curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    chmod +x wp-cli.phar
    sudo mv wp-cli.phar /usr/local/bin/wp
    wp --info

WP-CLI is a command-line interface that allows interaction with WordPress. This step downloads and installs WP-CLI. The chmod +x command makes it executable, and wp --info verifies that it has been successfully installed by displaying WP-CLI version and environment information.

9. Build the Plugin

- name: Build Plugin
  run: npm run build

In this step, the plugin’s build process is executed by running the npm-run-build script. This script is typically defined in your package.json file and may include tasks like compiling assets, bundling code, or preparing the plugin for distribution.

10. Deploy the Plugin to WordPress SVN

- name: WordPress Plugin Deploy
  id: deploy
  uses: 10up/action-wordpress-plugin-deploy@stable
  with:
    generate-zip: true
  env:
    SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
    SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
    BUILD_DIR: build

This is the core of the deployment process. The 10up/action-wordpress-plugin-deploy@stable action is a predefined GitHub Action built specifically to handle WordPress plugin deployments to the SVN repository.

  • generate-zip: true tells the action to generate a ZIP file of the plugin, which is necessary for deploying to SVN.
  • SVN_USERNAME and SVN_PASSWORD are pulled from GitHub Secrets to securely authenticate with the WordPress SVN repository.
  • BUILD_DIR is the directory where your built plugin resides. In this case, it’s set to build, which should match the output folder of your build process.

11. Create GitHub Release

- name: Create GitHub release
  uses: softprops/action-gh-release@v1
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

After deploying to SVN, this step creates a new release in your GitHub repository. It uses the softprops/action-gh-release@v1 action, which automatically tags and releases the current build as a GitHub release. The GITHUB_TOKEN is securely pulled from GitHub Secrets for authorization.

Summary

This workflow provides a powerful, automated way to deploy your WordPress plugin to the official WordPress plugin repository from GitHub. Each time you push a new version (via a Git tag), this workflow:

  1. Checks out your code from the repository.
  2. Installs necessary build tools and dependencies.
  3. Builds your plugin.
  4. Deploys it to the WordPress SVN repository.
  5. Creates a new GitHub release.

By automating the deployment process, you reduce the risk of manual errors and save time when releasing new versions of your plugin.

The Four Pillars of Object Oriented Programming

OOP is a programming paradigm that computer programmers must encounter in their life. This article assumes you are already familiar with Class & Objects. To enhance your OOP understanding four pillars are worth discussing. So, let’s jump into the details:

Inheritance

The very first pillar is inheritance & it’s totally connected with the real world. As we know, if a father has property then his son will inherit it. And yes every child is going to inherit it. In programming, inheritance complies with the same concept. Let’s see in the code:

	class Father {

		public $name = "Sr. John Doe";

		public function totalProperty() {
			return "USD 1000000";
		}
	}

	class Son extends Father {
		public $name = "John Doe";
	}

	$son = new Son();
	echo "{$son->name} inherit {$son->totalProperty()}"; 

Output: John Doe inherit USD 1000000

Here, we can see the Son class extends the Father class & a $son object. Though the Son class doesn’t contains the totalProperty() method still we can call it by using the son object, this is because of inheritance that has been done using the keyword extends! So if a class extends to another class then we call this class a child class & the main class (Father) is called a parent class. In a simple sense, this is inheritance. The child class will inherit all the properties & methods from the parent class except private data.

Polymorphism

At its base, polymorphism refers to many forms, but that’s not very helpful unless you understand it in the context of OOP. The real value of polymorphism is that objects with the same interface can be called to do different things. In a large complex structure (a great big program), additions and changes can blow the hinges off your program unless it has a common interface (from a parent class or interface). For example, the following program has two classes that share a common interface. The implementations of the interface are quite different: 

	interface ISpeed
	{
		public function speed();
	}

	class Jet implements ISpeed 
	{
		public function speed(){
			return 2500;
		}
	}

	class Car
	{
		public function speed() {
			return 100 + 50;
		}
	}

	$jet = new Jet();
	echo "Jet speed is {$jet->speed()} <br>";

	$car = new Car();
	echo "Car speed is {$car->speed()}";

Output: Jet speed is 2500
Car speed is 150

The two implementations of the ISpeed interface by the Jet and Car classes are very different. However, when making changes or additions within a given structure of a program, I can request or use the interface methods without having to worry about whether my program will crash or not.

One Name with Many Implementations

The easiest way to understand polymorphism is in the different implementations of an interface. The Jet class simply implements each method to return a primitive value, and the Car class makes an addition and then returns a value. Both used the same interface.

Encapsulation

In the previous two examples of inheritance & polymorphism, we have created classes & keep properties and methods inside them. This is basically called encapsulation! Yeah, as simple as it sounds. The term encapsulation simply makes things compact and hides unnecessary details. By using encapsulation, we can set visibility to expose information as per need & making staff secure. If we didn’t wrap properties & methods then it could be accessible from anywhere & it would be unorganized & unmanageable.

Class Abstraction

Abstraction in the real world

I’m a coffee addict. So, when I wake up in the morning, I go into my kitchen, switch on the coffee machine and make coffee. Sounds familiar?

Making coffee with a coffee machine is a good example of abstraction.

You need to know how to use your coffee machine to make coffee. You need to provide water and coffee beans, switch them on, and select the kind of coffee you want to get.

The thing you don’t need to know is how the coffee machine is working internally to brew a fresh cup of delicious coffee. You don’t need to know the ideal temperature of the water or the amount of ground coffee you need to use.

Someone else worried about that and created a coffee machine that now acts as an abstraction and hides all these details. You just interact with a simple interface that doesn’t require any knowledge about the internal implementation.

Abstraction in OOP

Objects in an OOP language provide an abstraction that hides the internal implementation details. Similar to the coffee machine in your kitchen, you just need to know which methods of the object are available to call and which input parameters are needed to trigger a specific operation. But you don’t need to understand how this method is implemented and which kinds of actions it has to perform to create the expected result.

	abstract class CoffeeMachine {

		// Child class must have to follow method signature
		public abstract function getBeans(): string;

		// Child class must have to follow method signature
		public abstract function getMilk(): string;

		// Making Coffee
		public function makeCoffee() {
			$beans = $this->getBeans();
			$milk  = $this->getMilk();
			return 'Hot Cappucino!!!';
		}
	}

	class CoffeeApp extends CoffeeMachine {

		private $beans;
		private $milk;

		public function __construct($beans, $milk) {
			$this->beans = $beans;
			$this->milk = $milk;
		}

		public function getBeans(): string {
			return $this->beans;
		}

		public function getMilk(): string {
			return $this->milk;
		}
	}

	// Client don't need to know coffee is getting ready
	// They just need to pass beans & milk
	$coffeeApp = new CoffeeApp('beans', 'milk');
	echo $coffeeApp->makeCoffee();

Output: Hot Cappucino!!!

Yeah, as a coffee lover, we do care about the output 😀 not what is happening inside the machine!

Dynamically Sanitize Multi-Dimensional Array Values by Using WordPress Functions

Data sanitization is crucial in WordPress. Even this is an essential security measurement. Every data from the user’s input must be sanitized as early as possible. WordPress provides many helper functions for data sanitization you can find here. Very easy & handy function! But the real scenario may not be straightforward.

What if we need to sanitize form data having a large set of data & sanitizing one by one field may feel cumbersome? So, to get rid of this we can create a helper function that can loop through all the array elements and sanitize them one by one for us. But a little gotcha here! Of course, we may not use the same sanitization function for each field. For example: for email sanitization, we need to use sanitize_email while for the post we will use wp_kses_post.

So let’s fix the above-discussed problem:

/**
 * Sanitize array, single or multi dimensional array
 * Explicitly setup how should a value sanitize by the
 * sanitize function.
 *
 * @see available sanitize func
 * https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/
 *
 * @param array $input array to sanitize.
 * @param array $sanitize_mapping single dimensional map key value
 * pair to set up sanitization process. Key name should by inside
 * input array and the value will be callable func.
 * For ex: [key1 => sanitize_email, key2 => wp_kses_post ]
 *
 * If key not passed then default sanitize_text_field will be used.
 *
 * @return array
 */
function sanitize_array( array $input, array $sanitize_mapping = array() ):array {
	$array = array();

	if ( is_array( $input ) && count( $input ) ) {
		foreach ( $input as $key => $value ) {
			if ( is_array( $value ) ) {
				$array[ $key ] = sanitize_array( $value );
			} else {
				$key = sanitize_text_field( $key );

				// If mapping exists then use callback.
				if ( isset( $sanitize_mapping[ $key ] ) ) {
					$callback = $sanitize_mapping[ $key ];
					$value    = call_user_func( $callback, wp_unslash( $value ) );
				} else {
					$value = sanitize_text_field( wp_unslash( $value ) );
				}
				$array[ $key ] = $value;
			}
		}
	}
	return is_array( $array ) && count( $array ) ? $array : array();
}

So the sanitize_array function is a cursive function that can do sanitization each array value using respective sanitization functions.

The first argument on the function is an array that could be single or multi-dimensional. And, the second argument is that is optional but we can tell which array element should use which function. A simple key value pair, where the key is the key name from the array and the value is the respective sanitization function name that we want to use for a particular value.

Hope you enjoyed it 😀

Suppress PHPCS Warnings Using Comments

PHPCS (code sniffer) is a great tool for linting & checking your codes against the set of rules. Along with PHPCS, as WordPress folk, we use WordPress coding standards (WPCS) as well. It is very useful to maintain coding standards, ensure output escaping, nonce verification, SQL escape, etc. But sometimes, there will be cases to avoid rules checking for specific code snippets.

Let’s discuss the useful comments to suppress warnings

To Ignore code snippets we can use the below comments:

// @codingStandardsIgnoreStart

// @codingStandardsIgnoreEnd

All the codes inside the above comments will be ignored

Ignore just the below line:

//phpcs:ignore

Ignore nonce verification warning:

//phpcs:disable WordPress.Security.NonceVerification.Recommended

Suppress PHPCS(WordPress.DB.PreparedSQL.InterpolatedNotPrepared)

//phpcs:ignore WordPress.DB.PreparedSQL

Ignore nonce verification missing warning

// phpcs:disable WordPress.Security.NonceVerification.Missing

Suppress PHPCS(Squiz.Commenting.FileComment.Missing)

//phpcs:ignore Generic.Commenting.DocComment.MissingShort

PHPCS(WordPress.Files.FileName.NotHyphenatedLowercase)

//phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase

There may have a lot more comments to suppress warnings. If you know others’ comments, feel free to share through the comments section below! Happy coding 😀

Abstract Factory Design Pattern with Example in PHP

Abstract factory method is useful for creating products of related family. Create objects of product from sub-classes. A family could have multiple member and each member could have variation among them but they behave similarly.

For example: Let’s consider a furniture family consist of member like chair, table, sofa. Here member may have different type in looks. Suppose chair may have different types like: modern, victorian, art deco. Similarly table and sofa may have different type as well.

4 Steps for implementing Abstract Factory Design Pattern

I have divided the implementation into four easy steps:

Step 1: Create Factory Abstract Class

Factory class will produce multiple product through abstract method.

abstract class FurnitureFactory
{
    abstract public static function createChair(): ChairInterface;

    abstract public static function createTable(): TableInterface;

    abstract public static function createSofa(): SofaInterface;
}

Step 2: Create Factory Concrete Class

Factory concrete class will extends the Factory class so that it implement abstract method. Factory concrete class will implement each distinct product variation and responsible for creating object of product.


class ModernFurniture extends FurnitureFactory
{
    public static function createChair(): ChairInterface
    {
        return new ModernChair();
    }
    public static function createTable(): TableInterface
    {
        return new ModernTable();
    }
    public static function createSofa(): SofaInterface
    {
        return new ModernSofa();
    }
}

Step 3: Interface of each Distinct Product

Interface will be implemented by the product class so that each product have consistency in their behaviour. This way we don’t have to worry about the variations. Since all variations will implement same interface we can also use property and method of class same way.

interface ChairInterface
{
    public function legs(): int;

    public function sitting();
}

interface TableInterface
{
    public function legs(): int;

    public function hasDrawer(): bool;
}

interface SofaInterface
{
    public function seats(): int;
    public function hasDivan(): bool;
}

Step 4: Declare Product Concrete Class for each Product

Each product will have separate class by implementing interface.

class ModernChair implements ChairInterface
{
    public function legs(): int
    {
        return 4;
    }

    public function sitting()
    {
        return 'fine';
    }
}

class ModernTable implements TableInterface
{
    public function legs(): int
    {
        return 4;
    }

    public function hasDrawer(): bool
    {
        return true;
    }
}

class ModernSofa implements SofaInterface
{
    public function seats(): int
    {
        return 5;
    }

    public function hasDivan(): bool
    {
        return false;
    }
}

Now our product is ready to use by the client code

$modern_chair = ModernFurniture::createChair();
echo $modern_chair->legs();

From this Modern Furniture class will can create table & sofa as well and can show users as relevant product.

In future we need more variations for the furniture we can simple create another variation Factory Concrete class without touching any other code 🙂