A WordPress plugin for starting a command palette plugin.
- Flush Permalinks
- Clear Cache
- Enable Plugins for Admins (Multisite)
Commands run in the:
- Block Editor
- Admin Panel
- Network Admin Panel
- Frontend
- PHP 7.4 or higher
- Node.js 14 or higher
- Composer
- Install dependencies:
npm install
composer install- Build assets:
npm run buildnpm run build- Build production assetsnpm run start- Start development server with hot reloadnpm run lint:js- Lint JavaScript filesnpm run lint:css- Lint CSS filesnpm run format- Format code
The plugin follows PSR-4 autoloading standards:
cmd-starter.php- Main plugin filephp/- PHP classes (PSR-4 namespace:CMDStarter)php/Commands.php- REST API endpoints for commandsphp/Functions.php- Main functions classsrc/- JavaScript source filessrc/commands/- Command palette componentscommands-admin.js- Admin area commands registrationcommands-block-editor.js- Block editor commands registrationcommands-frontend.js- Frontend commands registrationcommands-network.js- Network admin commands registrationcomponents/commands/- Individual command componentscomponents/modals/- Modal components for commands
build/- Compiled JavaScript assets (generated)vendor/- Composer dependencies (generated)
This plugin uses Webpack to bundle command files for different contexts (admin, block editor, frontend, network). Each command requires both a React component and a PHP REST API endpoint.
Create a new React component file in src/commands/components/commands/YourCommandName.js:
/**
* Command to [describe your command].
*/
import { useState } from 'react';
import { useCommand } from '@wordpress/commands';
import apiFetch from '@wordpress/api-fetch';
import ProcessingModal from '../modals/ProcessingModal';
import { __ } from '@wordpress/i18n';
// Optional: Add an icon (SVG element).
const YourIcon = <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
<path d="..." />
</svg>;
/**
* Hook to register the [Your Command Name] command.
*
* @return {JSX.Element|null} The YourCommandName component.
*/
export function YourCommandNameCommand() {
const [ isOpen, setIsOpen ] = useState( false );
const [ isLoading, setIsLoading ] = useState( false );
const [ message, setMessage ] = useState( '' );
const [ error, setError ] = useState( false );
const [ warning, setWarning ] = useState( false );
useCommand( {
name: 'dlx-cmd-starter-your-command-name',
label: 'Your Command Label',
icon: YourIcon, // Optional: Remove if no icon needed.
keywords: [ 'keyword1', 'keyword2', 'keyword3' ],
callback: () => {
setIsOpen( true );
setIsLoading( true );
setError( false );
setWarning( false );
setMessage( '' );
apiFetch( {
path: '/cmd-starter/v1/your_command_name',
method: 'POST',
} )
.then( ( result ) => {
setIsLoading( false );
if ( result.success ) {
setMessage( result.response || __( 'Command executed successfully.', 'cmd-starter' ) );
setTimeout( () => {
setIsOpen( false );
}, 2000 );
} else {
setError( true );
setMessage( result.response || __( 'Failed to execute command.', 'cmd-starter' ) );
}
} )
.catch( ( err ) => {
setIsLoading( false );
// Check if it's a permission error.
if ( err.code === 'rest_forbidden' || err.status === 401 || err.status === 403 ) {
setError( true );
setMessage( __( 'You do not have permission to execute this command.', 'cmd-starter' ) );
} else {
setError( true );
setMessage( err.message || __( 'An error occurred while executing the command.', 'cmd-starter' ) );
}
} );
},
context: 'admin', // Options: 'admin', 'site-editor', 'view'. Use 'admin' for both admin and block editor.
} );
return (
<ProcessingModal
title={ __( 'Your Command Title', 'cmd-starter' ) }
processingMessage={ __( 'Processing command…', 'cmd-starter' ) }
isOpen={ isOpen }
onClose={ () => setIsOpen( false ) }
isLoading={ isLoading }
message={ message }
error={ error }
warning={ warning }
/>
);
}Import and register your command in the appropriate registration file:
Add to src/commands/commands-admin.js:
import { YourCommandNameCommand } from './components/commands/YourCommandName';
// Inside the CommandsAdmin component:
const YourCommandModal = YourCommandNameCommand();
return (
<>
{ YourCommandModal }
{ /* ... other commands */ }
</>
);Add to src/commands/commands-block-editor.js:
import { YourCommandNameCommand } from './components/commands/YourCommandName';
// Inside the CommandsBlockEditor component:
const YourCommandModal = YourCommandNameCommand();
return (
<>
{ YourCommandModal }
{ /* ... other commands */ }
</>
);Add to src/commands/commands-frontend.js:
import { YourCommandNameCommand } from './components/commands/YourCommandName';
// Inside the CommandsFrontend component:
const YourCommandModal = YourCommandNameCommand();
return (
<>
{ YourCommandModal }
{ /* ... other commands */ }
</>
);Add to src/commands/commands-network.js:
import { YourCommandNameCommand } from './components/commands/YourCommandName';
// Inside the CommandsNetwork component:
const YourCommandModal = YourCommandNameCommand();
return (
<>
{ YourCommandModal }
{ /* ... other commands */ }
</>
);Add your REST API endpoint in php/Commands.php:
- Register the route in the
register_commands()method:
/**
* Register the commands.
*/
public function register_commands() {
// Your command endpoint.
register_rest_route(
'cmd-starter/v1',
'/your_command_name',
array(
'methods' => 'POST',
'callback' => array( $this, 'your_command_name' ),
'permission_callback' => function () {
return current_user_can( 'manage_options' ); // Adjust capability as needed.
},
)
);
// ... other routes.
}- Add the callback method:
/**
* Execute your command.
*
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function your_command_name() {
if ( ! current_user_can( 'manage_options' ) ) {
return new \WP_Error( 'rest_forbidden', __( 'You are not allowed to execute this command.', 'cmd-starter' ), array( 'status' => 403 ) );
}
// Execute your command logic here.
return new \WP_REST_Response(
array(
'success' => true,
'response' => __( 'Command executed successfully.', 'cmd-starter' ),
),
200
);
}After making changes, rebuild the assets:
npm run buildOr during development, use:
npm run startRun:
npm run zipThe webpack.config.js defines multiple entry points that correspond to different WordPress contexts:
cmds-block-editor- Loaded in the block editor.cmds-admin- Loaded in the admin area (non-block editor).cmds-frontend- Loaded on the frontend.cmds-network- Loaded in the network admin area.
Make sure to register your command in the appropriate registration file so it's bundled in the correct entry point.
