Welcome to the AI plugin development guide. This document provides everything you need to know to contribute to the plugin or create your own AI-powered experiments.
- Architecture Overview
- Creating a New Experiment
- Plugin API
- Development Workflow
- Additional Resources
Experiments are the core building blocks of the AI plugin. Each experiment represents a distinct piece of functionality that may utilize AI capabilities.
- Encapsulation: Each experiment is self-contained and can be reviewed independently
- Modularity: Experiments can be added/removed without affecting core functionality
- Extensibility: Third-party developers can register custom experiments via hooks
- Standards Compliance: All code follows WordPress coding standards
Create a new directory in includes/Experiments/ for your experiment:
mkdir -p includes/Experiments/My_ExperimentCreate your experiment class by extending Abstract_Feature:
<?php
/**
* My Experiment implementation.
*
* @package WordPress\AI\Experiments
*/
namespace WordPress\AI\Experiments\My_Experiment;
use WordPress\AI\Abstracts\Abstract_Feature;
use WordPress\AI\Asset_Loader;
/**
* My Experiment class.
*
* @since 0.1.0
*/
class My_Experiment extends Abstract_Feature {
/**
* {@inheritDoc}
*/
public static function get_id(): string {
return 'my-experiment';
}
/**
* {@inheritDoc}
*/
protected function load_metadata(): array {
return array(
'label' => __( 'My Experiment', 'ai' ),
'description' => __( 'Description of what my experiment does.', 'ai' ),
);
}
/**
* Registers the experiment's hooks and functionality.
*
* @since 0.1.0
*/
public function register(): void {
// Register your hooks here
add_action( 'init', array( $this, 'initialize' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
add_filter( 'the_content', array( $this, 'filter_content' ) );
}
/**
* Initializes the experiment.
*
* @since 0.1.0
*/
public function initialize(): void {
// Experiment initialization logic
}
/**
* Enqueues and localizes the admin script.
*
* @since 0.1.0
*
* @param string $hook_suffix The current admin page hook suffix.
*/
public function enqueue_assets( string $hook_suffix ): void {
Asset_Loader::enqueue_script( 'my-experiment', 'experiments/my-experiment' );
Asset_Loader::localize_script(
'my-experiment',
'MyExperimentData',
array(
'enabled' => $this->is_enabled(),
)
);
}
/**
* Filters content.
*
* @since 0.1.0
*
* @param string $content Post content.
* @return string Modified content.
*/
public function filter_content( string $content ): string {
// Experiment logic here
return $content;
}
}Register your experiment class via the wpai_default_feature_classes filter. The built-in experiments are registered through the Experiments class, but third-party experiments can be added the same way:
add_filter( 'wpai_default_feature_classes', function( $classes ) {
$classes[ My_Experiment::get_id() ] = My_Experiment::class;
return $classes;
} );Create a README.md in your experiment directory:
# My Experiment
Brief description of the experiment.
## Functionality
- What the experiment does
- How it works
- Any requirements
## Usage
Examples of how to use the experiment.
## Configuration
Any settings or filters available.If your experiment has requirements (PHP extensions, other plugins, etc.), implement validation in your constructor:
class My_Experiment extends Abstract_Experiment {
public function __construct() {
if ( ! extension_loaded( 'gd' ) ) {
throw new \RuntimeException(
__( 'This experiment requires the GD extension.', 'ai' )
);
}
parent::__construct();
}
}The plugin provides a set of hooks and filters to allow third-party developers to extend its functionality.
Developers can register their own experiments using the wpai_register_features action. This is the primary way to add new functionality to the plugin.
add_action( 'wpai_register_features', function( $registry ) {
$registry->register_feature( new My_Custom_Experiment() );
} );Modify the list of default experiment classes before they are instantiated:
add_filter( 'wpai_default_feature_classes', function( $feature_classes ) {
// Add a custom experiment
$feature_classes[ My_Custom_Experiment::get_id() ] = My_Custom_Experiment::class;
// Remove a default experiment
unset( $feature_classes['example-experiment'] );
return $feature_classes;
} );Experiments can be disabled using the wpai_feature_{$feature_id}_enabled filter:
// Disable a specific experiment by its ID
add_filter( 'wpai_feature_example-experiment_enabled', '__return_false' );
// Or with a custom callback
add_filter( 'wpai_feature_example-experiment_enabled', function( $enabled ) {
// Your custom logic here
return false;
} );Disable all experiments at once:
add_filter( 'wpai_features_enabled', '__return_false' );The plugin also includes the following action hooks:
wpai_register_features: Fires after default features are registered, receives$registryparameterwpai_features_initialized: Fires after all registered features have been initialized
The plugin provides a utility class for loading assets. This uses wp-scripts to build assets which are expected to live within the src/ directory. They will then be built into the build-scripts/ directory, where the asset loader will look for the files, pulling in the proper dependencies and versioning.
use WordPress\AI\Asset_Loader;
/**
* Enqueue a script.
*
* First argument is the script handle.
* The second argument is the script file name.
* This script file name should be in the build-scripts/ directory.
* The source script files should be in the src/ directory. If needed,
* you can add the entry point to the webpack.config.js file.
*/
Asset_Loader::enqueue_script( 'my-experiment', 'experiments/my-experiment' );
/**
* Enqueue a style.
*
* First argument is the style handle.
* The second argument is the style file name.
* This style file name should be in the build-scripts/ directory.
* The source style files should be in the src/ directory. If needed,
* you can add the entry point to the webpack.config.js file.
*/
Asset_Loader::enqueue_style( 'my-experiment', 'experiments/my-experiment' );
/**
* Localize a script.
*
* First argument is the script handle.
* The second argument is the data object name.
* The third argument is the data to localize.
* In this example, the data will be available in the script as `aiMyExperimentData`.
*/
Asset_Loader::localize_script(
'my-experiment',
'MyExperimentData',
array(
'my_data' => 'my data',
)
);git checkout -b feature/my-feature-nameFollow the steps in Creating a New Experiment above to build your experiment.
Create unit tests in tests/Unit/ for your experiment:
<?php
namespace WordPress\AI\Tests\Unit\Experiments\My_Experiment;
use WordPress\AI\Experiments\My_Experiment\My_Experiment;
use PHPUnit\Framework\TestCase;
class My_Experiment_Test extends TestCase {
public function test_experiment_metadata() {
$this->assertEquals( 'my-experiment', My_Experiment::get_id() );
$experiment = new My_Experiment();
$this->assertNotEmpty( $experiment->get_label() );
}
}Before submitting, ensure all quality checks pass. See CONTRIBUTING.md for the complete list of required checks including:
- Coding standards validation
- Static analysis
- Unit tests
Push your branch and create a pull request. Follow the contribution guidelines in CONTRIBUTING.md for:
- Branch naming conventions
- Commit message format
- Pull request requirements
- Code review process
- Contributing Guidelines - Code standards and contribution process
- Testing Strategy – Testing philosophy and guidelines
- Testing REST API Strategy – Guidelines specific to testing REST API integrations
- Example Experiment - Reference implementation
- WordPress Plugin Handbook
- Experiment Lifecycle - Defines how new Experiments land in the plugin and how they could graduate towards WordPress core
- WordPress AI Team
- GitHub Issues: Report bugs or request features
- WordPress Slack: Join the
#core-aichannel in Slack, see the WordPress Slack page for signup information; it is free to join. - Make WordPress AI: https://make.wordpress.org/ai/
GPL-2.0-or-later
