### Usage Example Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Example demonstrating how to retrieve and execute an ability. ```APIDOC ## Usage This section provides an example of how to use the `wp_get_ability` function to retrieve and execute an ability. ```php $ability = wp_get_ability( 'demo-plugin/my-ability' ); $result = $ability->execute( array( 'post_id' => 123 ) ); if ( is_wp_error( $result ) ) { echo $result->get_error_message(); } ``` ``` -------------------------------- ### Start Local WordPress Environment Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/index.mdx Start the local WordPress development environment using npm. ```bash npm run env:start ``` -------------------------------- ### Install Sentry SDK Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/sentry.mdx Install the Sentry SDK using Composer. This command should be run in your terminal. ```bash composer require sentry/sentry ``` -------------------------------- ### Install and Activate Free Plugin via WP-CLI Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/testing.mdx Configures the .wp-env.json to automatically install and activate a free WordPress.org plugin when the test environment starts. Use this for tests requiring specific free plugins. ```json { "lifecycleScripts": { "afterStart": " && wp-env run tests-cli wp plugin install advanced-custom-fields --activate" } } ``` -------------------------------- ### Install CopyWebpackPlugin Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Install the CopyWebpackPlugin to copy files as-is without processing. This is useful for fonts or pre-compiled libraries. ```bash npm install copy-webpack-plugin --save-dev ``` -------------------------------- ### Install Action Scheduler via Composer Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/action-scheduler.mdx Use Composer to install the Action Scheduler library. This command should be run in your project's root directory. ```bash composer require woocommerce/action-scheduler ``` -------------------------------- ### Basic Asset Enqueuing Examples Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Enqueue assets for specific admin pages or shortcodes using the `enqueue_entrypoint()` method. ```php // Enqueue on a specific admin page add_action('admin_enqueue_scripts', function($hook) { if ($hook !== 'settings_page_my-plugin') { return; } $this->enqueue_entrypoint('demo-plugin-admin'); }); // Enqueue for a shortcode public function render_shortcode(): string { $this->enqueue_entrypoint('demo-plugin-frontend'); return '
...
'; } ``` -------------------------------- ### Configure PHP Version in setup.yml Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/github-actions.mdx Set the desired PHP version for the setup environment in the .github/workflows/setup.yml file. ```yaml - uses: shivammathur/setup-php@v2 with: php-version: '8.2' ``` -------------------------------- ### Install AI Agent Skills Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/work-with-ai.mdx Use this command to install all agent skills from the upstream repository. This ensures your project has the necessary tools for AI-assisted workflows. ```bash npx skills add https://github.com/JUVOJustin/wordpress-plugin-boilerplate --skill=* ``` -------------------------------- ### Install Specific Version of Free Plugin via WP-CLI Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/testing.mdx Command to install and activate a specific version of a free plugin using WP-CLI within the test environment. Useful for testing compatibility with particular plugin versions. ```bash wp-env run tests-cli wp plugin install advanced-custom-fields --version=6.3.0 --activate ``` -------------------------------- ### Watch and Rebuild Assets During Development Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.md Starts a development server that watches for changes and automatically rebuilds assets. Ideal for active development. ```bash npm run start ``` -------------------------------- ### Front Matter Metadata Example Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/documentation.mdx Use front matter to provide metadata like title, short_title, and description for automated tooling. ```yaml --- title: Asset Bundling short_title: Bundling description: How scripts and styles are built and enqueued. --- ``` -------------------------------- ### Basic PHP Code Example Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.txt A simple PHP function example enclosed in backticks, often used for inline code references. ```php ``` -------------------------------- ### ACF JSON Sync Setup (Separate Class) Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/acf.mdx Implement ACF JSON synchronization using a dedicated class for better organization, especially for complex setups with multiple field groups. This involves defining methods for save and load paths and registering them with ACF filters. The separate class approach promotes modularity and maintainability. ```php $paths The current paths. * @return array The manipulated paths. */ public function load_path( array $paths ): array { // Optional: Remove default path // unset( $paths[0] ); $paths[] = DEMO_PLUGIN_PATH . 'acf-json'; return $paths; } } ``` ```php private function load_dependencies(): void { $this->loader = new Loader(); // Initialize ACF configuration new \Demo_Plugin\Integrations\ACF\Config(); } ``` -------------------------------- ### Create a PHPUnit Test Class Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/testing.mdx Define a new test class in the `tests/php` directory. This example demonstrates a basic test case extending `WP_UnitTestCase`. ```php assertTrue( true ); } } ``` -------------------------------- ### Configure Sentry SDK Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/sentry.mdx Configure Sentry with your DSN and set up a `before_send` callback to filter errors. This example filters out local environments and only sends errors originating from your plugin. ```php /** * Initialize Sentry before any other boot logic runs. */ private function init_sentry(): void { \Sentry\init( array( 'dsn' => 'https://your-dsn', 'release' => self::PLUGIN_VERSION, 'environment' => wp_get_environment_type(), 'traces_sample_rate' => 0.1, 'send_default_pii' => false, 'before_send' => function ( \Sentry\Event $event ) { // Filter events to this plugin and skip local environments. if ( wp_get_environment_type() === 'local' ) { return null; } foreach ( $event->getExceptions() as $ex ) { foreach ( $ex->getStacktrace()->getFrames() as $frame ) { if ( str_contains( $frame->getFile(), 'demo-plugin' ) ) { return $event; } } } return null; }, ) ); } ``` -------------------------------- ### ACF JSON Sync Setup (Direct Approach) Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/acf.mdx Configure ACF to save and load JSON field groups from the plugin's acf-json directory. This approach is suitable for simpler setups. It filters ACF settings to specify the save and load paths, ensuring that field groups are not saved in production environments. ```php /** * Load the required dependencies for this plugin. * * @since 1.0.0 * @access private */ private function load_dependencies(): void { $this->loader = new Loader(); // ACF JSON Support add_filter( 'acf/settings/save_json', function () { if ( wp_get_environment_type() !== 'production' ) { return DEMO_PLUGIN_PATH . 'acf-json'; } return ''; } ); add_filter( 'acf/settings/load_json', function ( $paths ) { $paths[] = DEMO_PLUGIN_PATH . 'acf-json'; return $paths; } ); } ``` -------------------------------- ### PHP Code Snippet Example Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/documentation.mdx Specify the language and a 'title' attribute for code snippets, indicating the file path. ```php private function enqueue_entrypoint( string $entry, array $localize_data = array() ): void ``` -------------------------------- ### Terminal Command Example Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/documentation.mdx Use the 'title' attribute for terminal sessions to indicate the context of the command. ```bash npm run build ``` -------------------------------- ### Markdown with Front Matter Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/documentation.mdx Combine front matter with Markdown content, starting with an intro paragraph or H2 heading. ```md --- title: Asset Bundling short_title: Bundling description: How scripts and styles are built and enqueued. --- Short intro paragraph. ## Overview ... ``` -------------------------------- ### Plugin Hook Example Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.txt This code snippet demonstrates how to hook into a WordPress action within your plugin's templates. Ensure the hook name matches your plugin's defined action. ```php ``` -------------------------------- ### Initialize Companion Plugin via Action Hook Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/companion-plugins.mdx This PHP snippet shows a companion plugin initializing its functionality by hooking into the 'demo_plugin_loaded' action and performing a version check. ```php // Initialize once the core plugin signals it is fully loaded. add_action( 'demo_plugin_loaded', 'acme_wpml_boot' ); function acme_wpml_boot( string $version ): void { // Version-gate against the core plugin's public API. if ( version_compare( $version, '2.0.0', '<' ) ) { return; } // ...attach to the core plugin's extension points here. } ``` -------------------------------- ### Synchronous Companion Plugin Initialization Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/companion-plugins.mdx This PHP snippet illustrates how a companion plugin can perform a synchronous check for the core plugin's readiness and version using 'did_action' and the 'DEMO_PLUGIN_VERSION' constant. ```php if ( did_action( 'demo_plugin_loaded' ) && version_compare( DEMO_PLUGIN_VERSION, '2.0.0', '>=' ) ) { acme_wpml_boot( DEMO_PLUGIN_VERSION ); } ``` -------------------------------- ### Create a New WordPress Block Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md Use the npm script 'create-block' to scaffold a new WordPress block. Registration is handled automatically. ```bash npm run create-block ``` -------------------------------- ### Initialize Sentry SDK Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/sentry.mdx Initialize Sentry within your plugin's dependency loading method. Ensure this is the very first statement to capture early errors. ```php /** * Load all plugin dependencies while making Sentry available first. */ private function load_dependencies(): void { $this->init_sentry(); $this->loader = new Loader(); $this->define_admin_hooks(); $this->define_public_hooks(); } ``` -------------------------------- ### Test Post Meta with WP_UnitTestCase Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/testing.mdx Demonstrates how to create a post, update its meta, and then assert the meta value using WordPress's built-in testing utilities. Each test is automatically rolled back. ```php post->create(); update_post_meta( $post_id, '_demo_flag', 'yes' ); $this->assertSame( 'yes', get_post_meta( $post_id, '_demo_flag', true ) ); } } ``` -------------------------------- ### Create New Plugin Project Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/index.mdx Use Composer to create a new WordPress plugin project from the boilerplate. ```bash composer create-project juvo/wordpress-plugin-boilerplate ``` -------------------------------- ### NPM Scripts for Frontend Development Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md NPM scripts for managing frontend assets, building the project, and running development servers. ```bash start build lint:js lint:style format create-block env:* ``` -------------------------------- ### Use jQuery Without Importing Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Demonstrates using jQuery globally via its aliases ($ and jQuery) after configuration. This code assumes the ProvidePlugin has been set up. ```javascript // Both work out of the box jQuery(document).ready(function() { console.log('jQuery ready'); }); // Or using the $ alias $(document).ready(function() { console.log('$ ready'); }); ``` -------------------------------- ### Load Action Scheduler Library in Plugin Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/action-scheduler.mdx Include the Action Scheduler bootstrap file in your main plugin file. Avoid using a file autoloader to ensure proper hook registration. ```php require_once plugin_dir_path( __FILE__ ) . 'vendor/woocommerce/action-scheduler/action-scheduler.php'; ``` -------------------------------- ### Starlight FileTree Component Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/documentation.mdx Utilize the Starlight FileTree component for consistent rendering of directory and file structures in documentation. ```mdx import { FileTree } from '@astrojs/starlight/components'; - src - ... ``` -------------------------------- ### Register 'demo_plugin_loaded' Action Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/companion-plugins.mdx This snippet shows how the core plugin registers the 'demo_plugin_loaded' action hook on 'plugins_loaded' at priority 0, passing its version. ```php add_action( 'plugins_loaded', static function (): void { do_action( 'demo_plugin_loaded', Demo_Plugin::PLUGIN_VERSION ); }, 0 ); ``` -------------------------------- ### Configure PHP Version and Tools in test-analyse.yml Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/github-actions.mdx Specify the PHP version and necessary tools like cs2pr in the .github/workflows/test-analyse.yml file. ```yaml - uses: shivammathur/setup-php@v2 with: php-version: '8.0' tools: cs2pr ``` -------------------------------- ### Configure Private Plugin Repository with Composer Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/testing.mdx Sets up Composer to use a private repository and require a premium plugin. This configuration is placed in tests/composer.json for managing private plugin dependencies. ```json { "repositories": [ { "type": "composer", "url": "https://composer.my-premium-plugin.com" } ], "require": { "vendor/my-premium-plugin": "*" }, "config": { "allow-plugins": { "composer/installers": true } } } ``` -------------------------------- ### Create Custom Ability Class Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Implement the `Ability_Interface` to define a new custom ability. This includes setting its name, label, description, category, input/output schemas, annotations, and execution logic. Ensure `show_rest` is true if it should be exposed via the REST API. ```php 'object', 'properties' => array( 'post_id' => array( 'type' => 'integer', 'minimum' => 1 ), ), 'required' => array( 'post_id' ), ); } public static function get_output_schema(): array { return array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean' ), 'title' => array( 'type' => 'string' ), ), ); } public static function get_annotations(): array { return array( 'readonly' => true, 'destructive' => false, 'idempotent' => true, ); } public static function show_rest(): bool { return true; } public static function get_mcp(): array { // Expose this ability on the MCP Adapter's default server. Return an empty // array instead to keep it off MCP (it can still be added to a custom server). return array( 'public' => true ); } public static function check_permissions( mixed $input = null ): bool|WP_Error { return current_user_can( 'read' ); } public static function execute( mixed $input = null ): mixed { $post = get_post( $input['post_id'] ); if ( ! $post ) { return new WP_Error( 'not_found', 'Post not found.', array( 'status' => 404 ) ); } return array( 'success' => true, 'title' => $post->post_title ); } } ``` -------------------------------- ### Ability Interface Methods Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Reference for the methods available on an Ability object. ```APIDOC ## Ability Interface Reference This section details the methods available for the Ability interface. ### Methods - **`get_name()`**: Returns a `string` representing the unique ID of the ability (e.g., `namespace/ability-name`). - **`get_label()`**: Returns a `string` for the display name of the ability. - **`get_description()`**: Returns a `string` describing what the ability does. - **`get_category()`**: Returns a `string` representing the category class name. - **`get_input_schema()`**: Returns an `array` representing the JSON Schema for the ability's input. - **`get_output_schema()`**: Returns an `array` representing the JSON Schema for the ability's output. - **`get_annotations()`**: Returns an `array` of behavioral hints (e.g., readonly, destructive, idempotent). - **`show_rest()`**: Returns a `bool` indicating if the ability should be exposed via REST API. - **`get_mcp()`**: Returns an `array` containing MCP exposure configuration, registered as `meta.mcp`. - **`check_permissions($input)`**: Returns a `bool` or `WP_Error` after checking permissions for the given input. - **`execute($input)`**: Returns `mixed` representing the result of the main logic after executing with the provided input. ``` -------------------------------- ### Define Custom Webpack Entrypoints Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Configure custom entrypoints in `webpack.config.js` to bundle frontend and admin assets. This merges with auto-discovered block entries from `@wordpress/scripts`. ```javascript const customEntries = { 'demo-plugin-frontend': [ path.resolve(__dirname, 'resources/frontend/js/app.js'), path.resolve(__dirname, 'resources/frontend/scss/app.scss'), ], 'demo-plugin-admin': [ path.resolve(__dirname, 'resources/admin/js/app.js'), path.resolve(__dirname, 'resources/admin/scss/app.scss'), ], }; ``` -------------------------------- ### Define 'DEMO_PLUGIN_VERSION' Constant Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/companion-plugins.mdx This snippet demonstrates defining the 'DEMO_PLUGIN_VERSION' constant as a public mirror of the core plugin's version for external checks. ```php if ( ! defined( 'DEMO_PLUGIN_VERSION' ) ) { define( 'DEMO_PLUGIN_VERSION', Demo_Plugin::PLUGIN_VERSION ); } ``` -------------------------------- ### Register WP-CLI Commands with Loader Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md Use the add_cli method in the Loader class to register WP-CLI commands. ```php add_cli(); ``` -------------------------------- ### Enqueue Entrypoint in Editor Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/create-blocks.mdx Use this snippet to enqueue shared styles and scripts from webpack-entrypoints in the block editor. This ensures consistent styling between the frontend and backend, especially when using global styles or server-side rendering for block previews. ```php /** * Enqueue entrypoint in the editor. * Should be used for shared styles and scripts */ add_action('enqueue_block_assets', function () { $this->enqueue_entrypoint( 'demo-plugin-frontend' ); }); ``` -------------------------------- ### Extract Translations Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/i18n.mdx Use this Composer script to generate a .pot file and update existing .po files for translations. Ensure WP-CLI is available. ```bash composer run i18n:extract ``` -------------------------------- ### Register Shortcodes with Loader Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md Register shortcodes using the add_shortcode method provided by the Loader class. ```php add_shortcode(); ``` -------------------------------- ### Action Scheduler Test Helper Class Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/action-scheduler.mdx A helper class for testing Action Scheduler functionality. It provides methods to run single queued jobs and all pending actions. ```php execute(), mark complete or failed. */ public static function run_action( int $action_id ): void { $runner = ActionScheduler_QueueRunner::instance(); $runner->process_action( $action_id, 'PHPUnit' ); } /** * Run all pending actions for a hook and optional group. */ public static function run_all_pending( string $hook, ?string $group = null ): int { $query = array( 'hook' => $hook, 'status' => ActionScheduler_Store::STATUS_PENDING, 'per_page' => 100, ); if ( null !== $group ) { $query['group'] = $group; } $action_ids = as_get_scheduled_actions( $query, 'ids' ); $processed = 0; foreach ( $action_ids as $action_id ) { self::run_action( (int) $action_id ); ++$processed; } return $processed; } } ``` -------------------------------- ### Provide Composer Authentication Credentials Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/testing.mdx Local authentication file for Composer to access private repositories. This file should not be committed to version control and contains credentials for private plugin sources. ```json { "http-basic": { "composer.my-premium-plugin.com": { "username": "your-license-email", "password": "your-license-key" } } } ``` -------------------------------- ### Compile Translations Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/i18n.mdx Use this Composer script to compile .po files into .mo, .json, and .php formats, making translations available to WordPress. This is automatically handled by the 'deploy' action with wp-env. ```bash composer run i18n:compile ``` -------------------------------- ### Run PHPUnit Application Tests Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.md Executes PHPUnit application tests within the `wp-env` environment. Ensure your local environment is running before executing. ```bash npm run test:php ``` -------------------------------- ### Category Interface Methods Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Reference for the methods available on a Category object. ```APIDOC ## Category Interface Reference This section details the methods available for the Category interface. ### Methods - **`get_slug()`**: Returns a `string` representing the unique slug (lowercase, hyphens only). - **`get_label()`**: Returns a `string` for the display name of the category. - **`get_description()`**: Returns a `string` describing the purpose of the category. - **`get_meta()`**: Returns an `array` containing optional metadata for the category. ``` -------------------------------- ### Run WordPress Coding Standards Checks Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.md Applies WordPress coding standards using PHP_CodeSniffer. Ensures code adheres to WordPress best practices. ```bash composer run phpcs ``` -------------------------------- ### Add a New Entrypoint to Webpack Configuration Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Extend the `customEntries` object in `webpack.config.js` to include a new feature entrypoint, bundling its associated JS and SCSS files. ```javascript const customEntries = { // ... existing entries 'my-new-feature': [ path.resolve(__dirname, 'resources/frontend/js/my-feature.js'), path.resolve(__dirname, 'resources/frontend/scss/my-feature.scss'), ], }; ``` -------------------------------- ### Execute an Ability Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Use `wp_get_ability` to retrieve an ability by its unique ID and then execute it with the necessary input. Handle potential `WP_Error` objects returned by the execution. ```php $ability = wp_get_ability( 'demo-plugin/my-ability' ); $result = $ability->execute( array( 'post_id' => 123 ) ); if ( is_wp_error( $result ) ) { echo $result->get_error_message(); } ``` -------------------------------- ### Configure CopyWebpackPlugin in Webpack Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Add the CopyWebpackPlugin to the `plugins` array in `webpack.config.js` to copy static files from `resources/static/` to `build/static/`. ```javascript const CopyPlugin = require('copy-webpack-plugin'); const extendConfig = (config) => ({ ...config, plugins: [ ...config.plugins, // ... existing plugins new CopyPlugin({ patterns: [ { from: 'resources/static', to: 'static', noErrorOnMissing: true }, ], }), ], // ... }); ``` -------------------------------- ### Run PHP Static Analysis Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.md Executes PHPStan for static analysis of PHP code. Helps identify bugs and potential issues without running the code. ```bash composer run phpstan ``` -------------------------------- ### Composer Scripts for Development Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md Common Composer scripts for PHP development tasks including static analysis, code formatting, and internationalization. ```bash phpstan phpcs phpcbf i18n:extract i18n:compile ``` -------------------------------- ### Register WordPress Hooks with Loader Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md Use the Loader class to register WordPress actions and filters. Avoid registering hooks directly in constructors. ```php add_action(); add_filter(); ``` -------------------------------- ### Register Abilities API with Loader Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/AGENTS.md Register implementations of the Abilities API (WP 6.9+) using the add_ability method via the Loader class. ```php add_ability(); ``` -------------------------------- ### Test Scheduled Export Job Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/integrations/action-scheduler.mdx Demonstrates testing a background job that exports user data to a CSV file. It shows the complete test pattern with proper cleanup in tear_down(). Always assert the job count before executing and assert the final state after the runner executes. ```php user->create( array( 'user_email' => 'test@example.com', 'role' => 'subscriber', ) ); update_user_meta( $user_id, 'company_name', 'Demo Corp' ); // Act: Schedule the export job $job_id = User_Data_Export::schedule( array( 'user_ids' => array( $user_id ), 'fields' => array( 'email', 'company_name' ), 'export_dir' => wp_upload_dir()['path'], ) ); // Assert: Verify job was queued correctly $this->assertIsInt( $job_id ); $this->assertGreaterThan( 0, $job_id ); $pending = as_get_scheduled_actions( array( 'hook' => User_Data_Export::AS_HOOK, 'status' => \ActionScheduler_Store::STATUS_PENDING, ), 'ids' ); $this->assertCount( 1, $pending ); // Execute: Run the job through the real AS runner Action_Scheduler_Test_Helper::run_action( $job_id ); // Assert: Verify the export result $export_file = get_option( 'demo_plugin_last_export_file' ); $this->assertNotFalse( $export_file ); $this->assertFileExists( $export_file ); $this->assertStringContainsString( 'test@example.com', file_get_contents( $export_file ) ); $this->assertStringContainsString( 'Demo Corp', file_get_contents( $export_file ) ); } public function tear_down(): void { // Cleanup: Unschedule leftover jobs to prevent state leakage as_unschedule_all_actions( User_Data_Export::AS_HOOK ); // Cleanup: Remove test export files $export_file = get_option( 'demo_plugin_last_export_file' ); if ( $export_file && file_exists( $export_file ) ) { wp_delete_file( $export_file ); } delete_option( 'demo_plugin_last_export_file' ); parent::tear_down(); } } ``` -------------------------------- ### Run Container-Side Scripts Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/wp-env.mdx Execute container-side scripts defined in composer.json using the 'env:cli' command. This allows running Composer scripts within the wp-env environment. ```bash npm run env:cli -- composer run my-script ``` -------------------------------- ### Add Host-Side Scripts to package.json Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/wp-env.mdx Define host-side scripts that interact with wp-env in your package.json. These scripts are executed from outside the container. ```json { "scripts": { "env:my-script": "wp-env run cli my-command" } } ``` -------------------------------- ### Create Data Retrieval Ability Category Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Define a new ability category for abilities that retrieve data without modifications. This class implements the `Ability_Category_Interface`. ```php $value . '-modified' ); $result = apply_filters( 'demo_plugin/example_value', 'before' ); $this->assertSame( 'before-modified', $result ); } } ``` -------------------------------- ### Register Ability in Plugin Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/abilities.mdx Register your custom ability class with the plugin's loader. Categories are automatically registered when referenced by abilities. ```php $this->loader->add_ability( Abilities\My_Ability::class ); ``` -------------------------------- ### Update PHP Version in Composer Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/github-actions.mdx Modify the 'require' constraint and 'config.platform' for PHP in composer.json. Remember to run 'composer update' afterwards. ```json { "require": { "php": ">=8.0" }, "config": { "platform": { "php": "8.0" } } } ``` -------------------------------- ### Stop Local WordPress Environment Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.md Stops the local WordPress environment. Use this command when you are finished with your development session. ```bash npm run env:stop ``` -------------------------------- ### Process SCSS Assets with Webpack Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Assets referenced via `url()` in SCSS files are automatically processed and copied to the `build/` directory by Webpack. This requires no additional configuration. ```scss .hero { background-image: url('../images/hero.jpg'); } ``` -------------------------------- ### Add Container-Side Scripts to composer.json Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/wp-env.mdx Define container-side scripts in composer.json, as Composer is available inside the wp-env container but npm is not. These scripts are executed within the container. ```json { "scripts": { "my-script": "wp some-command" } } ``` -------------------------------- ### Pass PHP Data to JavaScript Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Pass PHP data to JavaScript using the second parameter of `enqueue_entrypoint()`. The data becomes available in a global JavaScript object named after the plugin. ```php $this->enqueue_entrypoint('demo-plugin-frontend', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('demo_plugin_nonce'), 'user_id' => get_current_user_id(), ]); ``` -------------------------------- ### Upsert Translations Command Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/i18n.mdx This command can be used to instruct a coding agent to upsert translations for specified languages. It assumes the 'wp-plugin-bp' skill is available or can be run manually. ```bash /upsert-translations [lang1 lang2 ...] ``` -------------------------------- ### Run Commands Inside wp-env Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/wp-env.mdx Use the 'env:cli' script to execute commands within the wp-env container. This is useful for running Composer scripts or other CLI tools. ```bash npm run env:cli -- composer run i18n:compile npm run env:cli -- composer run phpstan ``` -------------------------------- ### Lint JavaScript Files Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/README.md Performs JavaScript linting to check for code style and potential errors. Helps maintain code quality. ```bash npm run lint:js ``` -------------------------------- ### Configure jQuery Global Aliases Source: https://github.com/juvojustin/wordpress-plugin-boilerplate/blob/main/docs/bundeling.mdx Configure webpack's ProvidePlugin to set global aliases for jQuery. This allows jQuery to be used without explicit imports in your JavaScript files. ```javascript plugins: [ ...config.plugins, new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', }), ] ```