These are a set of helper classes that will make WordPress plugin development easier
Read this Article on Medium to find out how to use these tools.
- Copy the extracted folder to your plugin directory
- Copy the .env.example to the root of your plugin and rename the file to .env. Then update the values in the .env
- If you would like to use the
wptools
command line interface:- Copy/move the
wptools
file to the root of your plugin - In your
.env
file, make sure to set theWORDPRESSTOOLS_DIR
andNAMESPACE
variables. - cd to the root of your plugin and run
php wptools
for the list of commands.
- Copy/move the
$ php wptools
- Import the
WordPressTools.php
file in your plugin main file and instantiate the class.
$wordpress_tools = new WordPressTools( __FILE__ );
To get the instance of the WordPressTools class from any file in your plugin, you can use the get_instance()
method.
NOTE: An exception is thrown if you have not created an instance of the WordPressTools class.
$wordpress_tools = WordPressTools::get_instance(__FILE__);
The WordPressTools provides an easy-to-use interface for managing database migrations.
Before you can use the migrations, you need to make sure you have done the following:
- Make sure you have created a folder to store the migrations in your plugin
- Make sure you have set the
MIGRATIONS_DIR
variable in your.env
file to this folder. - Make sure you have set the
TABLE_PREFIX
variable in your.env
file to this folder. The table prefix helps to avoid conflicts with other plugins.
To create a migration, you can use the make:migration
command.
The command takes one argument which is the name of the migration.
The name of the migration should be in the format create_table_name_table
or add_column_name_to_table
or remove_column_name_from_table
NOTE: The migration name should be in snake case.
$ php wptools make:migration create_users_table
You can also specify the name of the table using the --table
option
$ php wptools make:migration create_users_table --table=users
A new migration file will be created the migrations
folder.
The file name will be in the format YYYYMMDDHHMMSS_migration_name.php
You can specify the commands to run in the up
and down
methods of the migration class.
class CreateMessagesTable extends KMMigration {
protected $table_name = 'messages';
public function up( KMBlueprint $blueprint ) {
$blueprint->id();
$blueprint->string( 'contact_form' );
$blueprint->string( 'form_id' );
$blueprint->text( 'message' );
$blueprint->timestamps();
}
public function down( KMBlueprint $blueprint ) {
$blueprint->drop();
}
}
To run migrations, you need to add the code below to your plugin main file.
$wordpress_tools = new WordPressTools( __FILE__ );
$wordpress_tools->migration_manager->runMigrations();
Rolling back a migration can be done using the dropMigration
method in the migration_manager.
The method takes two arguments which are the name of the migration to be rolled back and an optional delete file boolean
flag, which is try by default.
NOTE Deleting a migration can lead to an infinite loop if the delete flag is set to false. We recommend you leave the delete flag as true.
$migration = $wordpress_tools->migration_manager->getMigration('create_users_table');
$wordpress_tools->migration_manager->dropMigration($migration);
You can also use the dropAll
method to drop all migrations.
$wordpress_tools->migration_manager->dropAll();
If you want to create a migration to update/alter a table, you must add the --update
flag when creating the
migration.
$ php wptools make:migration add_slug_to_questions_table --table=questions --update
An update migration will have the is_update
property set to true
class AddSlugToQuestionsTable extends KMMigration {
protected $table_name = 'questions';
protected $is_update = true;
public function up( KMBlueprint $blueprint ) {
$blueprint->string( 'slug', 100 );
}
public function down( KMBlueprint $blueprint ) {
$blueprint->dropColumn( 'slug' );
}
}
You can use models to query the database, without writing a single SQL command.
The WordPressTools provides an easy-to-use interface for query the database. Before you can use the model, you need to
make sure you have done the following:
- Make sure you have created a folder to store the models in your plugin
- Make sure you have set the
MODELS_DIR
variable in your.env
file to this folder.
To create a model, you can use the make:model
command.
The command takes one argument which is the name of the model.
The name of the model should be in the format ModelName
NOTE: The model name should be in Pascal case.
$ php wptools make:model User
The model will be created in the models
directory, a typical model will look like this:
class User extends KMModel {
}
By default, the User
model will automatically point to the users table in your plugin ([your_table_prefix]_users)
.
If you want to link the model
to another table, say the default WordPress users table, add the --table
flag to the command
$ php wptools make:model User --table=wp_users
The table property will be automatically set.
class User extends KMModel {
protected $table_name = 'wp_users';
}
The KMModel class provides two other options for customizing your model.
protected $timestamps = false;
protected $soft_delete = false;
- The
$timestamps
property, if set is true tells the model to automatically update the created_at and updated_at columns when creating or updating a record.
You can use the$blueprint->timestamps();
statement to add the created_at and updated_at columns to your migration. - The
$soft_delete
property, if set is true tells the model to automatically update the deleted_at column when deleting a record
You can use the$blueprint->softDelete();
statement to add the deleted_at column to your migration.
To add a new record, you can create a new instance of the model class and call the save
method on the instance.
$message = new Message();
$message->contact_form = 'cf7';
$message->form_id = 2;
$message->message = 'Hello World!';
$message->save();
To update a record, you can use the save
method on the model.
$message = Message::find(1);
$message->contact_form = 'cf7';
$message->form_id = 2;
$message->message = 'Hello World Edited!';
$message->save();
To delete a record, you can use the delete
method on the model.
$message = Message::find(1);
$message->delete();
If your migration has the soft_delete column, you can use the softDelete
method
$message = Message::find(1);
$message->softDelete();
The delete
method automatically calls the softDelete
method if the soft_delete property is set to true.
- You can retrieve a single record using the
find
method on the model.
$message = Message::find(1);
The find method takes one argument which is the id of the record to be retrieved. It returns the record or null if it
not found
- You can retrieve all records using the
all
method on the model.
$messages = Message::all();
The all method takes no argument and returns an array of all the records in the table.
- You can also retrieve records using the
where
method on the model.
$messages = Message::where( 'contact_form', '=', 'cf7' )->get();
- The model class supports method chaining
$messages = Message::where( 'contact_form', '=', 'cf7' )
->where( 'form_id', '=', 2 )
->get();
- The
first
method can be used to retrieve the first record that matches the query
$message = Message::where( 'contact_form', '=', 'cf7' )
->where( 'form_id', '=', 2 )
->first();
- The
take
method can be used to limit the number of records to be retrieved
$messages = Message::where( 'contact_form', '=', 'cf7' )
->where( 'form_id', '=', 2 )
->take( 10 );
- The
orderBy
method can be used to order the records
$messages = Message::where( 'contact_form', '=', 'cf7' )
->orderBy( 'created_at', 'desc' )
->get();
- The
groupBy
method can be used to group the records
$messages = Message::groupBy( 'contact_form' )
->get();
- The
orWhere
andandWhere
methods can be used to add or and where clauses to the query
$messages = Message::where( 'contact_form', '=', 'wp_form' )
->orWhere( 'contact_form', '=', 'cf7' )
->get();
- You can also perform joins using the
innerJoin
,leftJoin
, andrightJoin
methods
$applications = JobApplication::orderBy($sort_by, $order);
$applications->leftJoin('jobs')
->on('job_id', 'id')
->leftJoin('accounts')
->on('account_id', 'id');
$results = $applications->get();
The table prefix will be automatically added to the table name in the join. For example, jobs
will
become [table_prefix]_jobs
.
If you do not want to add the table prefix, you can set the second parameter of the join methods to false.
$applications = JobApplication::orderBy($sort_by, $order);
$applications->leftJoin('jobs', false)
->on('job_id', 'id')
->leftJoin('accounts', false)
->on('account_id', 'id');
$results = $applications->get();
- The
select
method can be used to get particular fields from the result
$messages = Message::select( ['id', 'message'] )->where( 'contact_form', '=', 'cf7' )
->where( 'form_id', '=', 2 )
->get();
or
$messages = Message::select( 'id, message' )->where( 'contact_form', '=', 'cf7' )
->where( 'form_id', '=', 2 )
->get();
- The
paginate
method can be used to paginate the results
$messages = Message::where( 'contact_form', '=', 'cf7' )
->where( 'form_id', '=', 2 )
->paginate( 10 );
The paginate
method takes two parameters: the first is the number of records to be displayed per page and the second
is the current page number.
$applications = JobApplication::paginate($per_page, $page)->orderBy($sort_by, $order);
$applications->leftJoin('jobs', false)
->on('job_id', 'id')
->leftJoin('accounts', false)
->on('account_id', 'id');
$select_fields = [
JobApplication::tableName() . '.*',
Job::tableName() . '.name AS job_name',
Job::tableName() . '.slug AS job_slug',
Account::tableName() . '.name AS account_name ',
];
$results = $applications->get( $select_fields);
The paginate method returns an array with the following properties:
$data = [
'data' => [], // the results
'page' => 1,
'totalPages' => 10,
'perPage' => 2,
'totalItems' => 100
];
You can use the KMValidator
class to validate your API requests.
$validator = KMValidator::make( [
'title' => 'required',
'content' => 'required',
], $_POST );
The KMValidator
class takes two parameters, the first is an array of rules and the second is the data to be validated.
To run the validation, call the validate
method on the validator object.
$validator->validate();
The validate
method returns a 400 response if the validation fails. It can also return a boolean.
Always check if the validation is successful before using the data.
if ( $validator->validate() ) {
// use the data
}
You can validate the request while instantiation the KMValidator
class
$validator = KMValidator::validate( [
'title' => 'required',
'content' => 'required',
], $_POST );
You can pass more than one rule to a field by separating them with a pipe |
.
$validator = KMValidator::validate( [
'title' => 'required|numeric',
'content' => 'required',
], $_POST );
The following rules are available:
required
- The field is requirednumeric
- The field must be a numeric valueinteger
- The field must be an integerbool
- The field must be a boolean value (true or false) or (1 or 0)pdf
- The field must be a pdf file
a. In a class
$menu_title = 'CF7 Form Filter';
$menu_page = new KMMenuPage(
array(
'page_title' => 'CF7 Form Filter',
'menu_title' => $menu_title,
'capability' => 'read',
'menu_slug' => 'kmcf7-message-filter',
'icon_url' => 'dashicons-filter',
'position' => null,
'function' => array(
$this,
'dashboard_view'
)
) );
$menu_page->run();
b. Not in a class
$menu_title = 'CF7 Form Filter';
$menu_page = new KMMenuPage(
array(
'page_title' => 'CF7 Form Filter',
'menu_title' => $menu_title,
'capability' => 'read',
'menu_slug' => 'kmcf7-message-filter',
'icon_url' => 'dashicons-filter',
'position' => null,
'function' => 'dashboard_view'
) );
$menu_page->run();
$menu_title = 'CF7 Form Filter';
$menu_page = new KMMenuPage(
array(
'page_title' => 'CF7 Form Filter',
'menu_title' => $menu_title,
'capability' => 'read',
'menu_slug' => 'kmcf7-message-filter',
'icon_url' => 'dashicons-filter',
'position' => null,
'function' => array(
$this,
'dashboard_view'
)
) );
$messages_page = new KMSubMenuPage(
array(
'parent_slug' => $menu_page->get_menu_slug(),
'page_title' => 'Blocked Messages',
'menu_title' => 'Blocked Messages',
'capability' => 'manage_options',
'menu_slug' => 'kmcf7-filtered-messages',
'position' => 1
'function' => array(
$this,
'messages_view'
)
) );
$menu_page->add_sub_menu_page( $messages_page );
$menu_page->run();
$settings_page = new KMSubMenuPage(
array(
'parent_slug' => $menu_page->get_menu_slug(),
'page_title' => 'Settings',
'menu_title' => 'Settings',
'capability' => 'manage_options',
'menu_slug' => 'kmcf7-message-filter-options',
'function' => array(
$this,
'settings_view'
),
'use_tabs' => true
) );
$settings_page->add_tab( 'basic', 'Basic Settings', array(
$this,
'status_tab_view'
), array( 'tab' => 'basic' ) );
$settings_page->add_tab( 'advanced', 'Advanced Settings', array(
$this,
'status_tab_view'
), array( 'tab' => 'advanced' ) );
$settings_page->add_tab( 'plugins', 'More Plugins', array(
$this,
'status_tab_view'
), array( 'tab' => 'plugins' ) );
$menu_page->add_sub_menu_page( $settings_page );
public function status_tab_view( $args ) {
switch ( $args['tab'] ) {
case 'plugins':
include "views/settings/plugins.php";
break;
case 'advanced':
include "views/settings/advanced.php";
break;
default:
include "views/settings/basic.php";
break;
}
}
The KMSetting
class is a wrapper for the WordPress Settings API. It provides a simple way to create settings page with sections and fields.
$settings = new KMSetting( 'kmcf7-message-filter-options&tab=advanced' );
$settings->add_section( 'kmcfmf_message_filter_advanced' );
$settings->add_field(
array(
'type' => 'checkbox',
'id' => 'kmcfmf_message_storage_toggle',
'label' => 'Disable file storage: ',
'tip' => "<span class='text-danger' style='color:red;'>Note: This is an experimental feature.</span><br/>Blocked messages are currently stored in a file. <br/>If you are unable to view blocked messages, disable this option. <br/> <b>Note: </b> Auto delete will be activated if it's currently not enabled"
)
);
$settings->add_field(
array(
'type' => 'checkbox',
'id' => 'kmcfmf_message_auto_delete_toggle',
'label' => 'Auto delete messages: ',
'tip' => ''
)
);
$settings->add_field(
array(
'type' => 'number',
'id' => 'kmcfmf_message_auto_delete_duration',
'label' => 'Number of days: ',
'tip' => '',
'min' => 1,
'max' => ''
)
);
$settings->add_field(
array(
'type' => 'select',
'id' => 'kmcfmf_message_auto_delete_duration',
'label' => 'Number of days: ',
'options' => array(
'1 Month' => '30',
'1 Day' => '1',
'3 Days' => '3',
'1 Week' => '7',
'2 Weeks' => '14',
),
// 'default_option' => ''
)
);
$settings->add_field(
array(
'type' => 'select',
'id' => 'kmcfmf_message_auto_delete_amount',
'label' => 'Number of messages to delete: ',
'options' => array(
'10 Messages' => '10',
'20 Messages' => '20',
'40 Messages' => '40',
'80 Messages' => '80',
),
// 'default_option' => ''
)
);
$settings->save();
$default_data = array(
'type' => '',
'id' => '',
'label' => '',
'tip' => '',
'min' => '',
'max' => '',
'input_class' => '', // class for input element
'class' => '', // class for parent element
'options' => array( 'Select a value' => '' ),
'default_option' => '',
'autocomplete' => 'on',
'placeholder' => ''
);
You can display the form using
$settings->show_form();
Alternatively, you don't want to use show_form()
, you can display the form with your own code
<?php
?>
<h2>Advanced Settings </h2>
<?php settings_errors(); ?>
<form method="post" action="options.php">
<?php
settings_fields( 'kmcfmf_message_filter_advanced' );
do_settings_sections( 'kmcf7-message-filter-options&tab=advanced' );
submit_button();
?>
</form>
<?php
-
Do not create the setting in the callback function of a menu or submenu, this will not allow the helper to hook into the
admin_init
action.You can either call the
show_form()
method in the menu page callback function or write the code manually to display the form (as shown above) in the callback function -
If you get
Options page not found in the allowed options list.
error, set your munu slug as the section id More Info Here