This page walks through a complete, minimal Wonderful Relations child plugin: the main file, the provider, a Modules\Init bootstrap, one ActionType and a composer.json. Copy and adapt.

Folder layout

your-plugin/
├── composer.json
├── your-plugin.php
└── src/
    ├── Plugin.php
    └── Modules/
        ├── Init.php
        └── Hello/
            └── Actions/
                └── ReturnText.php

composer.json

{
    "name": "your-vendor/your-plugin",
    "type": "wordpress-plugin",
    "autoload": {
        "psr-4": {
            "TS\\YourPlugin\\": "src/"
        }
    }
}

your-plugin.php

<?php
/**
 * Plugin Name: Your WR Child Plugin
 * Description: Demonstrates the minimal setup for a Wonderful Relations child plugin.
 * Version:     1.0.0
 * Author:      Your Vendor
 * Text Domain: your-plugin
 */
 
defined( 'ABSPATH' ) || exit;
 
require_once __DIR__ . '/vendor/autoload.php';
 
new \TS\YourPlugin\Plugin( __FILE__ );

src/Plugin.php

<?php
 
namespace TS\YourPlugin;
 
use TS\WonderfulRelations\System\ChildPlugin\AbstractChildPlugin;
use TS\WonderfulRelations\System\ChildPlugin\ChildPluginContext;
 
final class Plugin extends AbstractChildPlugin {
 
    private static string $main_file;
 
    public function __construct( string $main_file ) {
        self::$main_file = $main_file;
        parent::__construct();
    }
 
    protected static function make_context(): ChildPluginContext {
        return ChildPluginContext::create(
            'your-plugin',
            '1.0.0',
            'your-plugin',
            'Your WR Child Plugin',
            self::$main_file
        )
            ->with_modules_bootstrap( Modules\Init::class )
            ->with_dashboard_shortcode( 'your_plugin_dashboard' )
            ->with_menu_icon( 'dashicons-database' );
    }
}

src/Modules/Init.php

<?php
 
namespace TS\YourPlugin\Modules;
 
use TS\YourPlugin\Modules\Hello\Actions\ReturnText;
 
final class Init {
    public function __construct() {
        new ReturnText();
    }
}

src/Modules/Hello/Actions/ReturnText.php

<?php
 
namespace TS\YourPlugin\Modules\Hello\Actions;
 
use TS\WonderfulRelations\Includes\Constants;
use TS\WonderfulRelations\System\Action\ActionType\ActionType;
use TS\WonderfulRelations\System\Action\ActionType\ActionTypeCallback;
 
final class ReturnText extends ActionTypeCallback {
 
    public function __construct() {
        parent::__construct();
        new ActionType( 'your_plugin_return_text', $this );
    }
 
    public function execute_callback(): array {
        return array( Constants::CALLBACK_TYPE_STRING, 'Hello from your plugin!' );
    }
}

What happens at runtime

  1. your-plugin.php runs on plugins_loaded. It instantiates Plugin, which registers the activation hook and listens for wonderful_relations_plugin_loaded.
  2. Once WR has finished booting, install_plugin() runs and the default Kernel is constructed.
  3. Kernel instantiates Modules\Init, which instantiates ReturnText.
  4. ReturnText’s constructor instantiates ActionType, which hooks into register_new_action_type and is picked up by the central action type store.
  5. The frontend can now POST to wp_ajax_wr_ajax_process_entry with action=your_plugin_return_text and the callback fires.

Next steps

  • Add a Form to your plugin and ship its configuration in a Data Bundle.
  • Register a Task that runs on form save.
  • Move slow work into a Worker.
  • Restrict UI elements with Groups.