### Example: Activate Plugin with Custom Post Type and Flush Permalinks Source: https://developer.wordpress.org/plugins/the-basics/activation-deactivation-hooks This example demonstrates registering a custom post type and flushing permalinks upon plugin activation. It includes a helper function for setup and the activation hook registration. ```php /** * Register the "book" custom post type */ function pluginprefix_setup_post_type() { register_post_type( 'book', ['public' => true ] ); } add_action( 'init', 'pluginprefix_setup_post_type' ); /** * Activate the plugin. */ function pluginprefix_activate() { // Trigger our function that registers the custom post type plugin. pluginprefix_setup_post_type(); // Clear the permalinks after the post type has been registered. flush_rewrite_rules(); } register_activation_hook( __FILE__, 'pluginprefix_activate' ); ``` -------------------------------- ### Example: Activate Plugin with Custom Post Type and Flush Permalinks Source: https://developer.wordpress.org/plugins/plugin-basics/activation-deactivation-hooks This example demonstrates registering a custom post type and flushing permalinks upon plugin activation. It includes a helper function for setup and the activation hook registration. ```php /** * Register the "book" custom post type */ function pluginprefix_setup_post_type() { register_post_type( 'book', ['public' => true ] ); } add_action( 'init', 'pluginprefix_setup_post_type' ); /** * Activate the plugin. */ function pluginprefix_activate() { // Trigger our function that registers the custom post type plugin. pluginprefix_setup_post_type(); // Clear the permalinks after the post type has been registered. flush_rewrite_rules(); } register_activation_hook( __FILE__, 'pluginprefix_activate' ); ``` -------------------------------- ### Readme Header Information Example Source: https://developer.wordpress.org/plugins/wordpress-org/how-your-readme-txt-works This is an example of the required header information for a plugin's readme.txt file. Ensure all fields are correctly formatted. ```text === Plugin Name === Contributors: (this should be a list of wordpress.org userid's) Donate link: https://example.com/ Tags: tag1, tag2 Requires at least: 4.7 Tested up to: 5.4 Stable tag: 4.3 Requires PHP: 7.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Here is a short description of the plugin. This should be no more than 150 characters. No markup here. ``` -------------------------------- ### Complete Settings API Example Source: https://developer.wordpress.org/plugins/settings/using-settings-api This example demonstrates how to register a setting, add a section, and add a field to the 'reading' settings page. All functions are hooked into the 'admin_init' action. ```php function wporg_settings_init() { // register a new setting for "reading" page register_setting('reading', 'wporg_setting_name'); // register a new section in the "reading" page add_settings_section( 'wporg_settings_section', 'WPOrg Settings Section', 'wporg_settings_section_callback', 'reading' ); // register a new field in the "wporg_settings_section" section, inside the "reading" page add_settings_field( 'wporg_settings_field', 'WPOrg Setting', 'wporg_settings_field_callback', 'reading', 'wporg_settings_section' ); } /** * register wporg_settings_init to the admin_init action hook */ add_action('admin_init', 'wporg_settings_init'); /** * callback functions */ // section content cb function wporg_settings_section_callback() { echo '

WPOrg Section Introduction.

'; } // field content cb function wporg_settings_field_callback() { // get the value of the setting we've registered with register_setting() $setting = get_option('wporg_setting_name'); // output the field ?> 'some_value' ) ); } } ``` -------------------------------- ### WordPress Uninstall.php Example Source: https://developer.wordpress.org/plugins/plugin-basics/uninstall-methods The `uninstall.php` file is automatically executed when a plugin is uninstalled. Always check for the `WP_UNINSTALL_PLUGIN` constant to prevent direct access. This example shows how to delete options and drop a custom database table. ```php // if uninstall.php is not called by WordPress, die if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { die; } $option_name = 'wporg_option'; delete_option( $option_name ); // for site options in Multisite delete_site_option( $option_name ); // drop a custom database table global $wpdb; $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}mytable" ); ``` -------------------------------- ### Internationalization Text Domain Example Source: https://developer.wordpress.org/plugins/wordpress-org/plugin-developer-faq This example shows how to use the plugin's text domain for internationalization functions. Ensure this matches your plugin's slug for proper translation handling. ```php esc_html__('Hello', 'boaty-mcboatface'); ``` -------------------------------- ### Register Uninstall Hook Example Source: https://developer.wordpress.org/plugins/plugin-basics Example of using register_uninstall_hook to run a function when a plugin is deleted. This is crucial for removing all data created by the plugin, such as options or custom tables. ```php register_uninstall_hook( __FILE__, 'my_plugin_uninstall' ); function my_plugin_uninstall() { // Actions to perform on plugin uninstall // For example, delete all options created by the plugin delete_option( 'my_plugin_options' ); } ``` -------------------------------- ### Registering a callback to add a slider Source: https://developer.wordpress.org/plugins/hooks/advanced-topics This example shows how a callback function is registered using add_action to add a slider, which might be removed later for performance optimization. ```php function wporg_setup_slider() { // ... } add_action( 'template_redirect', 'wporg_setup_slider', 9 ); ``` -------------------------------- ### Translate PO File Manually (English Example) Source: https://developer.wordpress.org/plugins/internationalization/localization Manually translate strings in a PO file. The msgid field contains the original string, and the msgstr field is where the translation is entered. This example shows the structure before translation. ```text #: plugin-name.php:123 msgid "Page Title" msgstr "" ``` -------------------------------- ### Complete WordPress Plugin Installation Function Source: https://developer.wordpress.org/plugins/creating-tables-with-plugins A comprehensive function that includes creating/updating the database table, setting the character set and collation, and adding an initial version option. ```php prefix . 'liveshoutbox'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, name tinytext NOT NULL, text text NOT NULL, url varchar(55) DEFAULT '' NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); add_option( 'jal_db_version', $jal_db_version ); } function jal_install_data() { global $wpdb; $welcome_name = 'Mr. WordPress'; $welcome_text = 'Congratulations, you just completed the installation!'; $table_name = $wpdb->prefix . 'liveshoutbox'; $wpdb->insert( $table_name, array( 'time' => current_time( 'mysql' ), 'name' => $welcome_name, 'text' => $welcome_text, ) ); } ``` -------------------------------- ### Register Product Endpoints with GET and POST Source: https://developer.wordpress.org/plugins/rest-api/routes-endpoints Register routes for a collection of products and for creating new products. Use WP_REST_Server constants for methods to ensure compatibility. ```php /** * This is our callback function to return our products. * * @param WP_REST_Request $request This function accepts a rest request to process data. */ function prefix_get_products( $request ) { // In practice this function would fetch the desired data. Here we are just making stuff up. $products = array( '1' => 'I am product 1', '2' => 'I am product 2', '3' => 'I am product 3', ); return rest_ensure_response( $products ); } /** * This is our callback function to return a single product. * * @param WP_REST_Request $request This function accepts a rest request to process data. */ function prefix_create_product( $request ) { // In practice this function would create a product. Here we are just making stuff up. return rest_ensure_response( 'Product has been created' ); } /** * This function is where we register our routes for our example endpoint. */ function prefix_register_product_routes() { // Here we are registering our route for a collection of products and creation of products. register_rest_route( 'my-shop/v1', '/products', array( array( // By using this constant we ensure that when the WP_REST_Server changes, our readable endpoints will work as intended. 'methods' => WP_REST_Server::READABLE, // Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class. 'callback' => 'prefix_get_products', ), array( // By using this constant we ensure that when the WP_REST_Server changes, our create endpoints will work as intended. 'methods' => WP_REST_Server::CREATABLE, // Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class. 'callback' => 'prefix_create_product', ), ) ); } add_action( 'rest_api_init', 'prefix_register_product_routes' ); ``` -------------------------------- ### Make a DELETE Request with wp_remote_request Source: https://developer.wordpress.org/plugins/http-api Use wp_remote_request to make HTTP requests with methods not covered by specific functions like GET or POST. This example demonstrates how to send a DELETE request to a specified URL with custom arguments. ```php $args = array( 'method' => 'DELETE', ); $response = wp_remote_request( 'http://some-api.com/object/to/delete', $args ); ``` -------------------------------- ### Register Deactivation Hook Example Source: https://developer.wordpress.org/plugins/plugin-basics Example of using register_deactivation_hook to run a function when a plugin is deactivated. This is useful for cleaning up temporary data or resetting settings. ```php register_deactivation_hook( __FILE__, 'my_plugin_deactivate' ); function my_plugin_deactivate() { // Actions to perform on plugin deactivation // For example, delete temporary data or clear caches } ``` -------------------------------- ### Get Plugin File URL with plugins_url() Source: https://developer.wordpress.org/plugins/plugin-basics/determining-plugin-and-content-directories Use plugins_url() to get the full URL to a file within your plugin directory. This is useful for enqueuing scripts or styles. ```php plugins_url( 'myscript.js', __FILE__ ); ``` -------------------------------- ### Plugin Naming Conventions with Prefixes Source: https://developer.wordpress.org/plugins/wordpress-org/common-issues Demonstrates how to use unique prefixes for functions, classes, namespaces, options, and defines to prevent conflicts with other plugins or themes. ```php function ecpt_save_post() { // ... } class ECPT_Admin { // ... } namespace ECPT; update_option( 'ecpt_settings', $settings ); define( 'ECPT_LICENSE', true ); global $ecpt_options; ``` -------------------------------- ### Create Plugin Directory and File via Command Line Source: https://developer.wordpress.org/plugins/plugin-basics Navigate to the WordPress plugins directory and create a new directory for your plugin, followed by creating the main PHP file for your plugin. ```bash wordpress $ cd wp-content wp-content $ cd plugins plugins $ mkdir plugin-name plugins $ cd plugin-name plugin-name $ vi plugin-name.php ``` -------------------------------- ### Prepare Plugin for Submission Prompt Source: https://developer.wordpress.org/plugins/wordpress-org/using-the-mcp-server Use this prompt to initiate a guided checklist for preparing your plugin for submission to WordPress.org. The assistant will review guidelines, headers, readme, run Plugin Check, and more. ```text Help me prepare my plugin for submission to WordPress.org. ``` -------------------------------- ### Advanced Blueprint JSON for Rich Demo Environment Source: https://developer.wordpress.org/plugins/wordpress-org/previews-and-blueprints This advanced blueprint demonstrates installing plugins, themes, setting site options, and running custom PHP code. It's useful for creating comprehensive demo environments for users. ```json { "landingPage": "/wp-admin/post.php?post=5&action=edit", "preferredVersions": { "php": "7.4", "wp": "5.9" }, "phpExtensionBundles": [ "kitchen-sink" ], "steps": [ { "step": "login", "username": "admin", "password": "password" }, { "step": "installPlugin", "pluginZipFile": { "resource": "wordpress.org\/plugins", "slug": "my-imaginary-plugin-dependency" }, "options": { "activate": true } }, { "step": "installPlugin", "pluginZipFile": { "resource": "wordpress.org\/plugins", "slug": "my-imaginary-plugin" }, "options": { "activate": true } }, { "step": "installTheme", "themeZipFile": { "resource": "wordpress.org\/themes", "slug": "my-imaginary-theme" } }, { "step": "setSiteOptions", "options": { "some_required_option_1": "your_favorite_values", "some_required_option_2": "your_favorite_values" } }, { "step": "runPHP", "code": " 'wp-load.php required for WP functionality', 'post_status' => 'publish')); ?>" } ] } ``` -------------------------------- ### Sample WordPress Plugin Folder Structure Source: https://developer.wordpress.org/plugins/plugin-basics/best-practices Illustrates a recommended folder structure for a WordPress plugin, organizing core files, language files, and assets for admin and public sections. ```text /plugin-name plugin-name.php uninstall.php /languages /includes /admin /js /css /images /public /js /css /images ``` -------------------------------- ### Simple Blueprint JSON Configuration Source: https://developer.wordpress.org/plugins/wordpress-org/previews-and-blueprints Use this basic blueprint to set the landing page, preferred PHP and WordPress versions, and to log in to the WordPress admin. It's a good starting point for defining a Playground environment. ```json { "landingPage": "/wp-admin/edit.php", "preferredVersions": { "php": "7.4", "wp": "5.9" }, "phpExtensionBundles": [ "kitchen-sink" ], "steps": [ { "step": "login", "username": "admin", "password": "password" } ] } ``` -------------------------------- ### Create Local Directory for SVN Repository Source: https://developer.wordpress.org/plugins/wordpress-org/how-to-use-subversion Before checking out the SVN repository, create a local directory on your machine to house a copy of it. ```bash mkdir my-local-dir ``` -------------------------------- ### Translate PO File Manually (German Example) Source: https://developer.wordpress.org/plugins/internationalization/localization Manually translate strings in a PO file. Ensure the msgstr field contains the translated text. This example shows the German translation for 'Page Title'. ```text #: plugin-name.php:123 msgid "Page Title" msgstr "Seitentitel" ``` -------------------------------- ### GET /my-namespace/v1/books Attributes Source: https://developer.wordpress.org/plugins/rest-api/requests This snippet demonstrates how to retrieve attributes for a specific GET request to a custom endpoint. The attributes provide details about the endpoint's configuration, including supported methods, arguments, and callbacks. ```APIDOC ## GET /my-namespace/v1/books Attributes ### Description Retrieves the attributes registered for the `/my-namespace/v1/books` endpoint when a GET request is made. These attributes include supported methods, options, index visibility, and registered arguments. ### Method GET ### Endpoint `/my-namespace/v1/books` ### Parameters #### Query Parameters - **context** (string) - Optional - Scope under which the request is made; determines fields present in response. Enum: `view`, `embed`, `edit`. Default: `view`. - **page** (integer) - Optional - Current page of the collection. Minimum: 1. Default: 1. - **per_page** (integer) - Optional - Maximum number of items to be returned in result set. Minimum: 1, Maximum: 100. Default: 10. - **search** (string) - Optional - Limit results to those matching a string. - **after** (string) - Optional - Limit response to resources published after a given ISO8601 compliant date. Format: `date-time`. - **author** (array) - Optional - Limit result set to posts assigned to specific authors. Default: `[]`. - **author_exclude** (array) - Optional - Ensure result set excludes posts assigned to specific authors. Default: `[]`. - **before** (string) - Optional - Limit response to resources published before a given ISO8601 compliant date. Format: `date-time`. - **exclude** (array) - Optional - Ensure result set excludes specific ids. Default: `[]`. - **include** (array) - Optional - Limit result set to specific ids. Default: `[]`. - **offset** (integer) - Optional - Offset the result set by a specific number of items. - **order** (string) - Optional - Order sort attribute ascending or descending. Enum: `asc`, `desc`. Default: `desc`. - **orderby** (string) - Optional - Sort collection by object attribute. Enum: `date`, `relevance`, `id`, `include`, `title`, `slug`. Default: `date`. - **slug** (string) - Optional - Limit result set to posts with a specific slug. - **status** (string) - Optional - Limit result set to posts assigned a specific status; can be comma-delimited list of status types. Enum: `publish`, `future`, `draft`, `pending`, `private`, `trash`, `auto-draft`, `inherit`, `any`. Default: `publish`. - **filter** (object) - Optional - Filter parameters. ### Request Example ```json { "example": "request body" } ``` ### Response #### Success Response (200) - **methods** (object) - Supported HTTP methods for the endpoint. - **accept_json** (boolean) - Indicates if the endpoint accepts JSON. - **accept_raw** (boolean) - Indicates if the endpoint accepts raw data. - **show_in_index** (boolean) - Whether to show this endpoint in the index. - **args** (object) - Registered arguments for the endpoint. #### Response Example ```json { "methods": { "GET": true }, "accept_json": false, "accept_raw": false, "show_in_index": true, "args": { "context": { "description": "Scope under which the request is made; determines fields present in response.", "type": "string", "sanitize_callback": "sanitize_key", "validate_callback": "rest_validate_request_arg", "enum": [ "view", "embed", "edit" ], "default": "view" }, "page": { "description": "Current page of the collection.", "type": "integer", "default": 1, "sanitize_callback": "absint", "validate_callback": "rest_validate_request_arg", "minimum": 1 }, "per_page": { "description": "Maximum number of items to be returned in result set.", "type": "integer", "default": 10, "minimum": 1, "maximum": 100, "sanitize_callback": "absint", "validate_callback": "rest_validate_request_arg" }, "search": { "description": "Limit results to those matching a string.", "type": "string", "sanitize_callback": "sanitize_text_field", "validate_callback": "rest_validate_request_arg" }, "after": { "description": "Limit response to resources published after a given ISO8601 compliant date.", "type": "string", "format": "date-time", "validate_callback": "rest_validate_request_arg" }, "author": { "description": "Limit result set to posts assigned to specific authors.", "type": "array", "default": [], "sanitize_callback": "wp_parse_id_list", "validate_callback": "rest_validate_request_arg" }, "author_exclude": { "description": "Ensure result set excludes posts assigned to specific authors.", "type": "array", "default": [], "sanitize_callback": "wp_parse_id_list", "validate_callback": "rest_validate_request_arg" }, "before": { "description": "Limit response to resources published before a given ISO8601 compliant date.", "type": "string", "format": "date-time", "validate_callback": "rest_validate_request_arg" }, "exclude": { "description": "Ensure result set excludes specific ids.", "type": "array", "default": [], "sanitize_callback": "wp_parse_id_list" }, "include": { "description": "Limit result set to specific ids.", "type": "array", "default": [], "sanitize_callback": "wp_parse_id_list" }, "offset": { "description": "Offset the result set by a specific number of items.", "type": "integer", "sanitize_callback": "absint", "validate_callback": "rest_validate_request_arg" }, "order": { "description": "Order sort attribute ascending or descending.", "type": "string", "default": "desc", "enum": [ "asc", "desc" ], "validate_callback": "rest_validate_request_arg" }, "orderby": { "description": "Sort collection by object attribute.", "type": "string", "default": "date", "enum": [ "date", "relevance", "id", "include", "title", "slug" ], "validate_callback": "rest_validate_request_arg" }, "slug": { "description": "Limit result set to posts with a specific slug.", "type": "string", "validate_callback": "rest_validate_request_arg" }, "status": { "default": "publish", "description": "Limit result set to posts assigned a specific status; can be comma-delimited list of status types.", "enum": [ "publish", "future", "draft", "pending", "private", "trash", "auto-draft", "inherit", "any" ], "sanitize_callback": "sanitize_key", "type": "string", "validate_callback": [ {}, "validate_user_can_query_private_statuses" ] }, "filter": { "type": "object" } } } ``` }, { "language": "APIDOC", "code": "```php $request->get_attributes(); ```" } ] }, { "title": "POST /my-namespace/v1/books Attributes", "description": "This snippet demonstrates how to retrieve attributes for a specific POST request to a custom endpoint. The attributes provided for a POST request may differ from those for a GET request, reflecting the different operations supported.", "language": "APIDOC", "codeList": [ { "language": "APIDOC", "code": "## POST /my-namespace/v1/books Attributes\n\n### Description\nRetrieves the attributes registered for the `/my-namespace/v1/books` endpoint when a POST request is made. These attributes detail the specific configuration for POST operations on this route.\n\n### Method\nPOST\n\n### Endpoint\n`/my-namespace/v1/books`\n\n### Parameters\n#### Query Parameters\n- **context** (string) - Optional - Scope under which the request is made; determines fields present in response. Enum: `view`, `embed`, `edit`. Default: `view`.\n- **page** (integer) - Optional - Current page of the collection. Minimum: 1. Default: 1.\n- **per_page** (integer) - Optional - Maximum number of items to be returned in result set. Minimum: 1, Maximum: 100. Default: 10.\n- **search** (string) - Optional - Limit results to those matching a string.\n- **after** (string) - Optional - Limit response to resources published after a given ISO8601 compliant date. Format: `date-time`.\n- **author** (array) - Optional - Limit result set to posts assigned to specific authors. Default: `[]`.\n- **author_exclude** (array) - Optional - Ensure result set excludes posts assigned to specific authors. Default: `[]`.\n- **before** (string) - Optional - Limit response to resources published before a given ISO8601 compliant date. Format: `date-time`.\n- **exclude** (array) - Optional - Ensure result set excludes specific ids. Default: `[]`.\n- **include** (array) - Optional - Limit result set to specific ids. Default: `[]`.\n- **offset** (integer) - Optional - Offset the result set by a specific number of items.\n- **order** (string) - Optional - Order sort attribute ascending or descending. Enum: `asc`, `desc`. Default: `desc`.\n- **orderby** (string) - Optional - Sort collection by object attribute. Enum: `date`, `relevance`, `id`, `include`, `title`, `slug`. Default: `date`.\n- **slug** (string) - Optional - Limit result set to posts with a specific slug.\n- **status** (string) - Optional - Limit result set to posts assigned a specific status; can be comma-delimited list of status types. Enum: `publish`, `future`, `draft`, `pending`, `private`, `trash`, `auto-draft`, `inherit`, `any`. Default: `publish`.\n- **filter** (object) - Optional - Filter parameters.\n\n### Request Example\n```json\n{\n "example": "request body"\n}\n```\n\n### Response\n#### Success Response (200)\n- **methods** (object) - Supported HTTP methods for the endpoint.\n- **accept_json** (boolean) - Indicates if the endpoint accepts JSON.\n- **accept_raw** (boolean) - Indicates if the endpoint accepts raw data.\n- **show_in_index** (boolean) - Whether to show this endpoint in the index.\n- **args** (object) - Registered arguments for the endpoint.\n\n#### Response Example\n```json\n{\n "methods": {\n "POST": true\n },\n "accept_json": false,\n "accept_raw": false,\n "show_in_index": true,\n "args": {\n "context": {\n "description": "Scope under which the request is made; determines fields present in response.",\n "type": "string",\n "sanitize_callback": "sanitize_key",\n "validate_callback": "rest_validate_request_arg",\n "enum": [\n "view",\n "embed",\n "edit"\n ],\n "default": "view"\n },\n "page": {\n "description": "Current page of the collection.",\n "type": "integer",\n "default": 1,\n "sanitize_callback": "absint",\n "validate_callback": "rest_validate_request_arg",\n "minimum": 1\n },\n "per_page": {\n "description": "Maximum number of items to be returned in result set.",\n "type": "integer",\n "default": 10,\n "minimum": 1,\n "maximum": 100,\n "sanitize_callback": "absint",\n "validate_callback": "rest_validate_request_arg"\n },\n "search": {\n "description": "Limit results to those matching a string.",\n "type": "string",\n "sanitize_callback": "sanitize_text_field",\n "validate_callback": "rest_validate_request_arg"\n },\n "after": {\n "description": "Limit response to resources published after a given ISO8601 compliant date.",\n "type": "string",\n "format": "date-time",\n "validate_callback": "rest_validate_request_arg"\n },\n "author": {\n "description": "Limit result set to posts assigned to specific authors.",\n "type": "array",\n "default": [],\n "sanitize_callback": "wp_parse_id_list",\n "validate_callback": "rest_validate_request_arg"\n },\n "author_exclude": {\n "description": "Ensure result set excludes posts assigned to specific authors.",\n "type": "array",\n "default": [],\n "sanitize_callback": "wp_parse_id_list",\n "validate_callback": "rest_validate_request_arg"\n },\n "before": {\n "description": "Limit response to resources published before a given ISO8601 compliant date.",\n "type": "string",\n "format": "date-time",\n "validate_callback": "rest_validate_request_arg"\n },\n "exclude": {\n "description": "Ensure result set excludes specific ids.",\n "type": "array",\n "default": [],\n "sanitize_callback": "wp_parse_id_list"\n },\n "include": {\n "description": "Limit result set to specific ids.",\n "type": "array",\n "default": [],\n "sanitize_callback": "wp_parse_id_list"\n },\n "offset": {\n "description": "Offset the result set by a specific number of items.",\n "type": "integer",\n "sanitize_callback": "absint",\n "validate_callback": "rest_validate_request_arg"\n },\n "order": {\n "description": "Order sort attribute ascending or descending.",\n "type": "string",\n "default": "desc",\n "enum": [\n "asc",\n "desc"\n ],\n "validate_callback": "rest_validate_request_arg"\n },\n "orderby": {\n "description": "Sort collection by object attribute.",\n "type": "string",\n "default": "date",\n "enum": [\n "date",\n "relevance",\n "id",\n "include",\n "title",\n "slug"\n ],\n "validate_callback": "rest_validate_request_arg"\n },\n "slug": {\n "description": "Limit result set to posts with a specific slug.",\n "type": "string",\n "validate_callback": "rest_validate_request_arg"\n },\n "status": {\n "default": "publish",\n "description": "Limit result set to posts assigned a specific status; can be comma-delimited list of status types.",\n "enum": [\n "publish",\n "future",\n "draft",\n "pending",\n "private",\n "trash",\n "auto-draft",\n "inherit",\n "any"\n ],\n "sanitize_callback": "sanitize_key",\n "type": "string",\n "validate_callback": [\n {},\n "validate_user_can_query_private_statuses"\n ]\n },\n "filter": {\n "type": "object"\n }\n }\n}\n``` } ] } ] } ``` -------------------------------- ### Register Script with Defer Strategy Source: https://developer.wordpress.org/plugins/javascript/enqueuing Use 'strategy' => 'defer' in the $args array to load scripts after the DOM is ready but before window load events. Scripts execute in order. ```php wp_register_script( 'ajax-script-two', plugins_url( '/js/myscript.js', __FILE__ ), array( ajax-script ), '1.0.,0', array( 'strategy' => 'defer', ) ); ``` -------------------------------- ### Initialize and Use a WordPress Plugin Class Source: https://developer.wordpress.org/plugins/plugin-basics/best-practices Defines a basic WordPress plugin class with an init method for registering settings and a get_foo method for retrieving options. This snippet ensures the class is only defined if it doesn't already exist. ```php if ( ! class_exists( 'WPOrg_Plugin' ) ) { class WPOrg_Plugin { public static function init() { register_setting( 'wporg_settings', 'wporg_option_foo' ); } public static function get_foo() { return get_option( 'wporg_option_foo' ); } } WPOrg_Plugin::init(); WPOrg_Plugin::get_foo(); } ``` -------------------------------- ### Compile .mo Binaries from Command Line Source: https://developer.wordpress.org/plugins/internationalization/security Compile your own .mo binaries using msgfmt from the command line to ensure they are generated from the correct .po file and do not contain malicious strings. This method overrides headers in the .po file. ```bash msgfmt -cv -o /path/to/output.mo /path/to/input.po ``` -------------------------------- ### Get Role Object Source: https://developer.wordpress.org/plugins/users/roles-and-capabilities Retrieve a role object, including all its assigned capabilities, using the get_role() function. ```php get_role( $role ); ``` -------------------------------- ### Get Comments for a Post Source: https://developer.wordpress.org/plugins/rest-api/responses-2 Retrieves comments associated with a specific post ID. Requires the 'post' parameter. ```php // Grab a comments. function prefix_get_rest_comments( $request ) { if ( ! isset( $request['post'] ) ) { return new WP_Error( 'rest_bad_request', esc_html__( 'You must specify the post parameter for this request.', 'my-text-domain' ), array( 'status' => 400 ) ); } $data = array(); $comments = get_comments( array( 'post__in' => $request['post'] ) ); if ( empty( $comments ) ) { return array(); } foreach( $comments as $comment ) { $response = rest_ensure_response( $comment ); $response->add_links( prefix_prepare_comment_links( $comment ) ); $data[] = prefix_prepare_for_collection( $response ); } $response = rest_ensure_response( $data ); return $response; } ``` -------------------------------- ### Get Timestamp for Unscheduling Source: https://developer.wordpress.org/plugins/cron/scheduling-wp-cron-events Retrieve the timestamp of the next scheduled occurrence of a hook using `wp_next_scheduled()`. This is necessary for `wp_unschedule_event`. ```php $timestamp = wp_next_scheduled( 'bl_cron_hook' ); ``` -------------------------------- ### Example Plugin License Block Comment Source: https://developer.wordpress.org/plugins/plugin-basics/including-a-software-license Include this block comment near the top of your main plugin file to clearly state your plugin's license. Ensure you replace placeholders like {Plugin Name} and {URI to Plugin License}. ```php /* {Plugin Name} is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or any later version. {Plugin Name} is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with {Plugin Name}. If not, see {URI to Plugin License}. */ ``` -------------------------------- ### Blueprint File Notice Source: https://developer.wordpress.org/plugins/wordpress-org/previews-and-blueprints This message indicates that a blueprint file is missing and provides steps to create one for enabling user previews. It guides users through testing, fixing bugs, downloading, and committing the blueprint. ```text Your plugin does not yet have a blueprint file for user previews. If you'd like to enable previews, please follow these steps to create a blueprint. 1. Test your plugin in Playground. 2. Fix any bugs in your plugin that prevent it from working in Playground. 3. Download blueprint.json 4. Commit your blueprint to svn. ``` -------------------------------- ### Get Single Post with Links Source: https://developer.wordpress.org/plugins/rest-api/responses-2 Retrieves a single post by ID and adds HAL links for related resources, such as comments. ```php // Grab a post. function prefix_get_rest_post( $request ) { $id = (int) $request['id']; $post = get_post( $id ); $response = rest_ensure_response( array( $post ) ); $response->add_links( prefix_prepare_post_links( $post ) ); return $response; } ``` -------------------------------- ### Get Single Comment with Links Source: https://developer.wordpress.org/plugins/rest-api/responses-2 Retrieves a single comment by ID and adds HAL links, including a link to its parent post. ```php // Grab a comment. function prefix_get_rest_comment( $request ) { $id = (int) $request['id']; $post = get_comment( $id ); $response = rest_ensure_response( $comment ); $response->add_links( prefix_prepare_comment_links( $comment ) ); return $response; } ``` -------------------------------- ### Register Product Routes with Path Variable Source: https://developer.wordpress.org/plugins/rest-api/routes-endpoints Register routes for a collection of products and individual products using a numerical path variable. This example includes callback functions for fetching data and handling errors. ```php /** * This is our callback function to return our products. * * @param WP_REST_Request $request This function accepts a rest request to process data. */ function prefix_get_products( $request ) { // In practice this function would fetch the desired data. Here we are just making stuff up. $products = array( '1' => 'I am product 1', '2' => 'I am product 2', '3' => 'I am product 3', ); return rest_ensure_response( $products ); } /** * This is our callback function to return a single product. * * @param WP_REST_Request $request This function accepts a rest request to process data. */ function prefix_get_product( $request ) { // In practice this function would fetch the desired data. Here we are just making stuff up. $products = array( '1' => 'I am product 1', '2' => 'I am product 2', '3' => 'I am product 3', ); // Here we are grabbing the 'id' path variable from the $request object. WP_REST_Request implements ArrayAccess, which allows us to grab properties as though it is an array. $id = (string) $request['id']; if ( isset( $products[ $id ] ) ) { // Grab the product. $product = $products[ $id ]; // Return the product as a response. return rest_ensure_response( $product ); } else { // Return a WP_Error because the request product was not found. In this case we return a 404 because the main resource was not found. return new WP_Error( 'rest_product_invalid', esc_html__( 'The product does not exist.', 'my-text-domain' ), array( 'status' => 404 ) ); } // If the code somehow executes to here something bad happened return a 500. return new WP_Error( 'rest_api_sad', esc_html__( 'Something went horribly wrong.', 'my-text-domain' ), array( 'status' => 500 ) ); } /** * This function is where we register our routes for our example endpoint. */ function prefix_register_product_routes() { // Here we are registering our route for a collection of products. register_rest_route( 'my-shop/v1', '/products', array( // By using this constant we ensure that when the WP_REST_Server changes our readable endpoints will work as intended. 'methods' => WP_REST_Server::READABLE, // Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class. 'callback' => 'prefix_get_products', ) ); // Here we are registering our route for single products. The (?P[\d]+) is our path variable for the ID, which, in this example, can only be some form of positive number. register_rest_route( 'my-shop/v1', '/products/(?P[\d]+)', array( // By using this constant we ensure that when the WP_REST_Server changes our readable endpoints will work as intended. 'methods' => WP_REST_Server::READABLE, // Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class. 'callback' => 'prefix_get_product', ) ); } add_action( 'rest_api_init', 'prefix_register_product_routes' ); ``` -------------------------------- ### Commit Initial Plugin Version to SVN Source: https://developer.wordpress.org/plugins/wordpress-org/how-to-use-subversion After adding your files, commit the changes back to the central SVN repository with a descriptive commit message. ```bash my-local-dir/ $ svn ci -m 'Adding first version of my plugin' > Adding trunk/my-plugin.php > Adding trunk/readme.txt > Transmitting file data . > Committed revision 11326. ``` -------------------------------- ### Sanitize and Escape User Input Source: https://developer.wordpress.org/plugins/wordpress-org/common-issues Always sanitize user input before escaping it for output. This example uses sanitize_text_field and esc_html to process POST data. ```php echo esc_html(sanitize_text_field($_POST['example'])); ``` -------------------------------- ### Conditional Edit Link Example Source: https://developer.wordpress.org/plugins/users/roles-and-capabilities Display an 'Edit' link only if the current user has the 'edit_posts' capability. This snippet is typically used within template files. ```php if ( current_user_can( 'edit_posts' ) ) { edit_post_link( esc_html__( 'Edit', 'wporg' ), '

', '

' ); } ``` -------------------------------- ### Sample WordPress Plugin Folder Structure Source: https://developer.wordpress.org/plugins/the-basics/best-practices A recommended folder structure for organizing WordPress plugin files, including main plugin files, language files, and separate directories for admin and public assets. ```text /plugin-name plugin-name.php uninstall.php /languages /includes /admin /js /css /images /public /js /css /images ```