by shewa | Nov 24, 2024 | WordPress
You may encounter this issue in WordPress 6.7:
Function _load_textdomain_just_in_time was called incorrectly.
WordPress now warns developers if they are loading translations too early in a plugin or theme, before the current user is known. Existing functions like load_plugin_textdomain()
and load_theme_textdomain()
were updated to defer the actual loading to the existing just-in-time translation logic in core. This reduces the likelihood of triggering the warning, and even improves performance in some situations by avoiding loading translations if they are not needed on a given page. Here’s how you can fix this issue with straightforward solutions.
Possible Solutions
Use Correct Hooks for Loading Text Domain
If your plugin or theme is calling load_plugin_textdomain
or load_theme_textdomain
functions before WordPress has initialized properly, you need to call these functions on the appropriate hooks like after_setup_theme
or init
.
Here’s an example for each:
add_action( 'init', function () {
load_plugin_textdomain( 'your-textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
});
For themes
add_action( 'after_setup_theme', function () {
load_theme_textdomain( 'your-textdomain', get_template_directory() . '/languages' );
});
Adjust get_plugin_data
Usage
If you’re using the get_plugin_data
function to read plugin metadata, it might load translations earlier than intended. To prevent this, pass false
as the third argument when calling the function:
$plugin_data = get_plugin_data( __FILE__, true, false );
Debug the Issue
If the problem persists, debugging can help pinpoint the root cause. Add the following snippet to your plugin or theme to track where _load_textdomain_just_in_time
is being called:
add_action(
'doing_it_wrong_run',
static function ( $function_name ) {
if ( '_load_textdomain_just_in_time' === $function_name ) {
debug_print_backtrace();
}
}
);
This snippet will output a stack trace in your debug log whenever _load_textdomain_just_in_time
is called incorrectly. You can use this information to identify and resolve the issue.
Need More Help?
If you’ve tried these solutions and the issue persists, feel free to reach out for assistance. Debugging text domain issues can sometimes require a closer look at your code setup
Let me know in the comments or contact me directly for further support!
I am professional Web Designer & Developer. I have 5+ years of experience in relevant field. Currently I am working for a private software company named “Ollyo” as a Senior Staff Software Engineer.
by shewa | Sep 15, 2024 | Workflow
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:
- Checks out your code from the repository.
- Installs necessary build tools and dependencies.
- Builds your plugin.
- Deploys it to the WordPress SVN repository.
- 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.
I am professional Web Designer & Developer. I have 5+ years of experience in relevant field. Currently I am working for a private software company named “Ollyo” as a Senior Staff Software Engineer.
by shewa | Apr 2, 2023 | OOP, PHP
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!
I am professional Web Designer & Developer. I have 5+ years of experience in relevant field. Currently I am working for a private software company named “Ollyo” as a Senior Staff Software Engineer.
by shewa | Nov 30, 2022 | Data Security, WordPress
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 😀
I am professional Web Designer & Developer. I have 5+ years of experience in relevant field. Currently I am working for a private software company named “Ollyo” as a Senior Staff Software Engineer.
by shewa | Jul 23, 2022 | PHP, PHPCS, WPCS
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 😀
I am professional Web Designer & Developer. I have 5+ years of experience in relevant field. Currently I am working for a private software company named “Ollyo” as a Senior Staff Software Engineer.