Initial commit
This commit is contained in:
337
templates/examples/ajax-handler.php
Normal file
337
templates/examples/ajax-handler.php
Normal file
@@ -0,0 +1,337 @@
|
||||
<?php
|
||||
/**
|
||||
* Example: AJAX handlers
|
||||
*
|
||||
* This example shows how to:
|
||||
* - Register AJAX handlers for logged-in and non-logged-in users
|
||||
* - Verify nonces for CSRF protection
|
||||
* - Check user capabilities
|
||||
* - Sanitize input and return JSON responses
|
||||
* - Enqueue scripts with localized data
|
||||
*
|
||||
* @package YourPlugin
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue AJAX script
|
||||
*/
|
||||
function yourprefix_enqueue_ajax_script() {
|
||||
wp_enqueue_script(
|
||||
'yourprefix-ajax',
|
||||
plugins_url( 'js/ajax-example.js', __FILE__ ),
|
||||
array( 'jquery' ),
|
||||
'1.0.0',
|
||||
true
|
||||
);
|
||||
|
||||
// Localize script with AJAX URL and nonce
|
||||
wp_localize_script(
|
||||
'yourprefix-ajax',
|
||||
'yourprefixAjax',
|
||||
array(
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'yourprefix_ajax_nonce' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'wp_enqueue_scripts', 'yourprefix_enqueue_ajax_script' );
|
||||
|
||||
/**
|
||||
* AJAX handler for logged-in users
|
||||
*/
|
||||
function yourprefix_ajax_save_data() {
|
||||
// Verify nonce
|
||||
check_ajax_referer( 'yourprefix_ajax_nonce', 'nonce' );
|
||||
|
||||
// Check user capability
|
||||
if ( ! current_user_can( 'edit_posts' ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Permission denied', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Get and sanitize input
|
||||
$name = isset( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : '';
|
||||
$email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : '';
|
||||
$age = isset( $_POST['age'] ) ? absint( $_POST['age'] ) : 0;
|
||||
|
||||
// Validate input
|
||||
if ( empty( $name ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Name is required', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
if ( ! is_email( $email ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Invalid email address', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Process data (example: save to database)
|
||||
$result = yourprefix_save_user_data( $name, $email, $age );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => $result->get_error_message(),
|
||||
) );
|
||||
}
|
||||
|
||||
// Return success response
|
||||
wp_send_json_success( array(
|
||||
'message' => __( 'Data saved successfully', 'your-plugin' ),
|
||||
'data' => array(
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'age' => $age,
|
||||
),
|
||||
) );
|
||||
}
|
||||
add_action( 'wp_ajax_yourprefix_save_data', 'yourprefix_ajax_save_data' );
|
||||
|
||||
/**
|
||||
* AJAX handler for non-logged-in users
|
||||
*/
|
||||
function yourprefix_ajax_public_action() {
|
||||
// Verify nonce (still required for public AJAX)
|
||||
check_ajax_referer( 'yourprefix_ajax_nonce', 'nonce' );
|
||||
|
||||
// Get and sanitize input
|
||||
$query = isset( $_POST['query'] ) ? sanitize_text_field( $_POST['query'] ) : '';
|
||||
|
||||
if ( empty( $query ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Query is required', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Process query (example: search posts)
|
||||
$results = yourprefix_search_posts( $query );
|
||||
|
||||
wp_send_json_success( array(
|
||||
'message' => __( 'Search completed', 'your-plugin' ),
|
||||
'results' => $results,
|
||||
) );
|
||||
}
|
||||
add_action( 'wp_ajax_yourprefix_public_action', 'yourprefix_ajax_public_action' );
|
||||
add_action( 'wp_ajax_nopriv_yourprefix_public_action', 'yourprefix_ajax_public_action' );
|
||||
|
||||
/**
|
||||
* AJAX handler for fetching posts
|
||||
*/
|
||||
function yourprefix_ajax_load_posts() {
|
||||
// Verify nonce
|
||||
check_ajax_referer( 'yourprefix_ajax_nonce', 'nonce' );
|
||||
|
||||
// Get parameters
|
||||
$page = isset( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
|
||||
$per_page = isset( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : 10;
|
||||
$category = isset( $_POST['category'] ) ? absint( $_POST['category'] ) : 0;
|
||||
|
||||
// Query posts
|
||||
$args = array(
|
||||
'post_type' => 'post',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $page,
|
||||
'post_status' => 'publish',
|
||||
);
|
||||
|
||||
if ( $category > 0 ) {
|
||||
$args['cat'] = $category;
|
||||
}
|
||||
|
||||
$query = new WP_Query( $args );
|
||||
|
||||
$posts = array();
|
||||
if ( $query->have_posts() ) {
|
||||
while ( $query->have_posts() ) {
|
||||
$query->the_post();
|
||||
$posts[] = array(
|
||||
'id' => get_the_ID(),
|
||||
'title' => get_the_title(),
|
||||
'excerpt' => get_the_excerpt(),
|
||||
'url' => get_permalink(),
|
||||
'date' => get_the_date(),
|
||||
);
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
|
||||
wp_send_json_success( array(
|
||||
'posts' => $posts,
|
||||
'total_pages' => $query->max_num_pages,
|
||||
'found_posts' => $query->found_posts,
|
||||
) );
|
||||
}
|
||||
add_action( 'wp_ajax_yourprefix_load_posts', 'yourprefix_ajax_load_posts' );
|
||||
add_action( 'wp_ajax_nopriv_yourprefix_load_posts', 'yourprefix_ajax_load_posts' );
|
||||
|
||||
/**
|
||||
* AJAX handler for deleting item
|
||||
*/
|
||||
function yourprefix_ajax_delete_item() {
|
||||
// Verify nonce
|
||||
check_ajax_referer( 'yourprefix_ajax_nonce', 'nonce' );
|
||||
|
||||
// Check user capability
|
||||
if ( ! current_user_can( 'delete_posts' ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Permission denied', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Get item ID
|
||||
$item_id = isset( $_POST['item_id'] ) ? absint( $_POST['item_id'] ) : 0;
|
||||
|
||||
if ( $item_id === 0 ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Invalid item ID', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Check if item exists
|
||||
$post = get_post( $item_id );
|
||||
if ( ! $post ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Item not found', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Delete item
|
||||
$result = wp_trash_post( $item_id );
|
||||
|
||||
if ( ! $result ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Failed to delete item', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
wp_send_json_success( array(
|
||||
'message' => __( 'Item deleted successfully', 'your-plugin' ),
|
||||
'item_id' => $item_id,
|
||||
) );
|
||||
}
|
||||
add_action( 'wp_ajax_yourprefix_delete_item', 'yourprefix_ajax_delete_item' );
|
||||
|
||||
/**
|
||||
* AJAX handler for uploading file
|
||||
*/
|
||||
function yourprefix_ajax_upload_file() {
|
||||
// Verify nonce
|
||||
check_ajax_referer( 'yourprefix_ajax_nonce', 'nonce' );
|
||||
|
||||
// Check user capability
|
||||
if ( ! current_user_can( 'upload_files' ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Permission denied', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Check if file was uploaded
|
||||
if ( empty( $_FILES['file'] ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'No file uploaded', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Handle file upload
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
|
||||
$file = $_FILES['file'];
|
||||
|
||||
// Validate file type
|
||||
$allowed_types = array( 'image/jpeg', 'image/png', 'image/gif' );
|
||||
if ( ! in_array( $file['type'], $allowed_types, true ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( 'Invalid file type. Only JPG, PNG, and GIF are allowed.', 'your-plugin' ),
|
||||
) );
|
||||
}
|
||||
|
||||
// Upload file
|
||||
$attachment_id = media_handle_upload( 'file', 0 );
|
||||
|
||||
if ( is_wp_error( $attachment_id ) ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => $attachment_id->get_error_message(),
|
||||
) );
|
||||
}
|
||||
|
||||
// Get attachment data
|
||||
$attachment_url = wp_get_attachment_url( $attachment_id );
|
||||
|
||||
wp_send_json_success( array(
|
||||
'message' => __( 'File uploaded successfully', 'your-plugin' ),
|
||||
'attachment_id' => $attachment_id,
|
||||
'attachment_url' => $attachment_url,
|
||||
) );
|
||||
}
|
||||
add_action( 'wp_ajax_yourprefix_upload_file', 'yourprefix_ajax_upload_file' );
|
||||
|
||||
/**
|
||||
* Helper function: Save user data
|
||||
*
|
||||
* @param string $name User name.
|
||||
* @param string $email User email.
|
||||
* @param int $age User age.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
function yourprefix_save_user_data( $name, $email, $age ) {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'yourprefix_users';
|
||||
|
||||
$result = $wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'age' => $age,
|
||||
),
|
||||
array( '%s', '%s', '%d' )
|
||||
);
|
||||
|
||||
if ( false === $result ) {
|
||||
return new WP_Error( 'db_error', __( 'Database error', 'your-plugin' ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function: Search posts
|
||||
*
|
||||
* @param string $query Search query.
|
||||
* @return array
|
||||
*/
|
||||
function yourprefix_search_posts( $query ) {
|
||||
$args = array(
|
||||
'post_type' => 'post',
|
||||
's' => $query,
|
||||
'posts_per_page' => 10,
|
||||
'post_status' => 'publish',
|
||||
);
|
||||
|
||||
$search_query = new WP_Query( $args );
|
||||
|
||||
$results = array();
|
||||
if ( $search_query->have_posts() ) {
|
||||
while ( $search_query->have_posts() ) {
|
||||
$search_query->the_post();
|
||||
$results[] = array(
|
||||
'id' => get_the_ID(),
|
||||
'title' => get_the_title(),
|
||||
'url' => get_permalink(),
|
||||
);
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
274
templates/examples/custom-post-type.php
Normal file
274
templates/examples/custom-post-type.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
/**
|
||||
* Example: Register custom post type and taxonomy
|
||||
*
|
||||
* This example shows how to:
|
||||
* - Register a custom post type
|
||||
* - Register a custom taxonomy
|
||||
* - Link taxonomy to post type
|
||||
* - Flush rewrite rules on activation
|
||||
* - Use proper labels and arguments
|
||||
*
|
||||
* @package YourPlugin
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom post type
|
||||
*/
|
||||
function yourprefix_register_book_post_type() {
|
||||
$labels = array(
|
||||
'name' => _x( 'Books', 'Post type general name', 'your-plugin' ),
|
||||
'singular_name' => _x( 'Book', 'Post type singular name', 'your-plugin' ),
|
||||
'menu_name' => _x( 'Books', 'Admin Menu text', 'your-plugin' ),
|
||||
'name_admin_bar' => _x( 'Book', 'Add New on Toolbar', 'your-plugin' ),
|
||||
'add_new' => __( 'Add New', 'your-plugin' ),
|
||||
'add_new_item' => __( 'Add New Book', 'your-plugin' ),
|
||||
'new_item' => __( 'New Book', 'your-plugin' ),
|
||||
'edit_item' => __( 'Edit Book', 'your-plugin' ),
|
||||
'view_item' => __( 'View Book', 'your-plugin' ),
|
||||
'all_items' => __( 'All Books', 'your-plugin' ),
|
||||
'search_items' => __( 'Search Books', 'your-plugin' ),
|
||||
'parent_item_colon' => __( 'Parent Books:', 'your-plugin' ),
|
||||
'not_found' => __( 'No books found.', 'your-plugin' ),
|
||||
'not_found_in_trash' => __( 'No books found in Trash.', 'your-plugin' ),
|
||||
'featured_image' => _x( 'Book Cover Image', 'Overrides the "Featured Image" phrase', 'your-plugin' ),
|
||||
'set_featured_image' => _x( 'Set cover image', 'Overrides the "Set featured image" phrase', 'your-plugin' ),
|
||||
'remove_featured_image' => _x( 'Remove cover image', 'Overrides the "Remove featured image" phrase', 'your-plugin' ),
|
||||
'use_featured_image' => _x( 'Use as cover image', 'Overrides the "Use as featured image" phrase', 'your-plugin' ),
|
||||
'archives' => _x( 'Book archives', 'The post type archive label', 'your-plugin' ),
|
||||
'insert_into_item' => _x( 'Insert into book', 'Overrides the "Insert into post"/"Insert into page" phrase', 'your-plugin' ),
|
||||
'uploaded_to_this_item' => _x( 'Uploaded to this book', 'Overrides the "Uploaded to this post"/"Uploaded to this page" phrase', 'your-plugin' ),
|
||||
'filter_items_list' => _x( 'Filter books list', 'Screen reader text for the filter links', 'your-plugin' ),
|
||||
'items_list_navigation' => _x( 'Books list navigation', 'Screen reader text for the pagination', 'your-plugin' ),
|
||||
'items_list' => _x( 'Books list', 'Screen reader text for the items list', 'your-plugin' ),
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'labels' => $labels,
|
||||
'description' => __( 'Books managed by your plugin', 'your-plugin' ),
|
||||
'public' => true,
|
||||
'publicly_queryable' => true,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array( 'slug' => 'books' ),
|
||||
'capability_type' => 'post',
|
||||
'has_archive' => true,
|
||||
'hierarchical' => false,
|
||||
'menu_position' => 20,
|
||||
'menu_icon' => 'dashicons-book',
|
||||
'show_in_rest' => true, // Enable Gutenberg editor
|
||||
'rest_base' => 'books',
|
||||
'rest_controller_class' => 'WP_REST_Posts_Controller',
|
||||
'supports' => array(
|
||||
'title',
|
||||
'editor',
|
||||
'author',
|
||||
'thumbnail',
|
||||
'excerpt',
|
||||
'comments',
|
||||
'custom-fields',
|
||||
'revisions',
|
||||
),
|
||||
);
|
||||
|
||||
register_post_type( 'book', $args );
|
||||
}
|
||||
add_action( 'init', 'yourprefix_register_book_post_type' );
|
||||
|
||||
/**
|
||||
* Register custom taxonomy (Hierarchical - like Categories)
|
||||
*/
|
||||
function yourprefix_register_genre_taxonomy() {
|
||||
$labels = array(
|
||||
'name' => _x( 'Genres', 'taxonomy general name', 'your-plugin' ),
|
||||
'singular_name' => _x( 'Genre', 'taxonomy singular name', 'your-plugin' ),
|
||||
'search_items' => __( 'Search Genres', 'your-plugin' ),
|
||||
'all_items' => __( 'All Genres', 'your-plugin' ),
|
||||
'parent_item' => __( 'Parent Genre', 'your-plugin' ),
|
||||
'parent_item_colon' => __( 'Parent Genre:', 'your-plugin' ),
|
||||
'edit_item' => __( 'Edit Genre', 'your-plugin' ),
|
||||
'update_item' => __( 'Update Genre', 'your-plugin' ),
|
||||
'add_new_item' => __( 'Add New Genre', 'your-plugin' ),
|
||||
'new_item_name' => __( 'New Genre Name', 'your-plugin' ),
|
||||
'menu_name' => __( 'Genre', 'your-plugin' ),
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'hierarchical' => true, // true = like categories, false = like tags
|
||||
'labels' => $labels,
|
||||
'show_ui' => true,
|
||||
'show_admin_column' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array( 'slug' => 'genre' ),
|
||||
'show_in_rest' => true,
|
||||
);
|
||||
|
||||
register_taxonomy( 'genre', array( 'book' ), $args );
|
||||
}
|
||||
add_action( 'init', 'yourprefix_register_genre_taxonomy' );
|
||||
|
||||
/**
|
||||
* Register non-hierarchical taxonomy (like Tags)
|
||||
*/
|
||||
function yourprefix_register_book_tag_taxonomy() {
|
||||
$labels = array(
|
||||
'name' => _x( 'Book Tags', 'taxonomy general name', 'your-plugin' ),
|
||||
'singular_name' => _x( 'Book Tag', 'taxonomy singular name', 'your-plugin' ),
|
||||
'search_items' => __( 'Search Book Tags', 'your-plugin' ),
|
||||
'popular_items' => __( 'Popular Book Tags', 'your-plugin' ),
|
||||
'all_items' => __( 'All Book Tags', 'your-plugin' ),
|
||||
'edit_item' => __( 'Edit Book Tag', 'your-plugin' ),
|
||||
'update_item' => __( 'Update Book Tag', 'your-plugin' ),
|
||||
'add_new_item' => __( 'Add New Book Tag', 'your-plugin' ),
|
||||
'new_item_name' => __( 'New Book Tag Name', 'your-plugin' ),
|
||||
'separate_items_with_commas' => __( 'Separate book tags with commas', 'your-plugin' ),
|
||||
'add_or_remove_items' => __( 'Add or remove book tags', 'your-plugin' ),
|
||||
'choose_from_most_used' => __( 'Choose from the most used book tags', 'your-plugin' ),
|
||||
'not_found' => __( 'No book tags found.', 'your-plugin' ),
|
||||
'menu_name' => __( 'Book Tags', 'your-plugin' ),
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'hierarchical' => false, // Non-hierarchical (like tags)
|
||||
'labels' => $labels,
|
||||
'show_ui' => true,
|
||||
'show_admin_column' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array( 'slug' => 'book-tag' ),
|
||||
'show_in_rest' => true,
|
||||
);
|
||||
|
||||
register_taxonomy( 'book_tag', array( 'book' ), $args );
|
||||
}
|
||||
add_action( 'init', 'yourprefix_register_book_tag_taxonomy' );
|
||||
|
||||
/**
|
||||
* Customize archive page query for books
|
||||
*/
|
||||
function yourprefix_modify_book_archive_query( $query ) {
|
||||
// Only modify main query on frontend for book archives
|
||||
if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'book' ) ) {
|
||||
// Show 12 books per page
|
||||
$query->set( 'posts_per_page', 12 );
|
||||
|
||||
// Order by title
|
||||
$query->set( 'orderby', 'title' );
|
||||
$query->set( 'order', 'ASC' );
|
||||
}
|
||||
}
|
||||
add_action( 'pre_get_posts', 'yourprefix_modify_book_archive_query' );
|
||||
|
||||
/**
|
||||
* Add custom columns to book admin list
|
||||
*/
|
||||
function yourprefix_add_book_columns( $columns ) {
|
||||
$new_columns = array();
|
||||
|
||||
foreach ( $columns as $key => $value ) {
|
||||
$new_columns[ $key ] = $value;
|
||||
|
||||
// Add genre column after title
|
||||
if ( 'title' === $key ) {
|
||||
$new_columns['genre'] = __( 'Genres', 'your-plugin' );
|
||||
$new_columns['book_tags'] = __( 'Tags', 'your-plugin' );
|
||||
}
|
||||
}
|
||||
|
||||
return $new_columns;
|
||||
}
|
||||
add_filter( 'manage_book_posts_columns', 'yourprefix_add_book_columns' );
|
||||
|
||||
/**
|
||||
* Populate custom columns
|
||||
*/
|
||||
function yourprefix_populate_book_columns( $column, $post_id ) {
|
||||
if ( 'genre' === $column ) {
|
||||
$genres = get_the_terms( $post_id, 'genre' );
|
||||
if ( $genres && ! is_wp_error( $genres ) ) {
|
||||
$genre_list = array();
|
||||
foreach ( $genres as $genre ) {
|
||||
$genre_list[] = sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
esc_url( add_query_arg( array( 'genre' => $genre->slug ), admin_url( 'edit.php?post_type=book' ) ) ),
|
||||
esc_html( $genre->name )
|
||||
);
|
||||
}
|
||||
echo implode( ', ', $genre_list );
|
||||
} else {
|
||||
echo '—';
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'book_tags' === $column ) {
|
||||
$tags = get_the_terms( $post_id, 'book_tag' );
|
||||
if ( $tags && ! is_wp_error( $tags ) ) {
|
||||
$tag_list = array();
|
||||
foreach ( $tags as $tag ) {
|
||||
$tag_list[] = esc_html( $tag->name );
|
||||
}
|
||||
echo implode( ', ', $tag_list );
|
||||
} else {
|
||||
echo '—';
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'manage_book_posts_custom_column', 'yourprefix_populate_book_columns', 10, 2 );
|
||||
|
||||
/**
|
||||
* Make columns sortable
|
||||
*/
|
||||
function yourprefix_sortable_book_columns( $columns ) {
|
||||
$columns['genre'] = 'genre';
|
||||
return $columns;
|
||||
}
|
||||
add_filter( 'manage_edit-book_sortable_columns', 'yourprefix_sortable_book_columns' );
|
||||
|
||||
/**
|
||||
* Flush rewrite rules on plugin activation
|
||||
*/
|
||||
function yourprefix_activate() {
|
||||
// Register post types and taxonomies
|
||||
yourprefix_register_book_post_type();
|
||||
yourprefix_register_genre_taxonomy();
|
||||
yourprefix_register_book_tag_taxonomy();
|
||||
|
||||
// CRITICAL: Flush rewrite rules to prevent 404 errors
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
register_activation_hook( __FILE__, 'yourprefix_activate' );
|
||||
|
||||
/**
|
||||
* Flush rewrite rules on plugin deactivation
|
||||
*/
|
||||
function yourprefix_deactivate() {
|
||||
// Flush rewrite rules
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
register_deactivation_hook( __FILE__, 'yourprefix_deactivate' );
|
||||
|
||||
/**
|
||||
* Query books by genre
|
||||
*
|
||||
* Example usage in theme templates
|
||||
*/
|
||||
function yourprefix_get_books_by_genre( $genre_slug, $posts_per_page = 10 ) {
|
||||
$args = array(
|
||||
'post_type' => 'book',
|
||||
'posts_per_page' => $posts_per_page,
|
||||
'tax_query' => array(
|
||||
array(
|
||||
'taxonomy' => 'genre',
|
||||
'field' => 'slug',
|
||||
'terms' => $genre_slug,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return new WP_Query( $args );
|
||||
}
|
||||
243
templates/examples/meta-box.php
Normal file
243
templates/examples/meta-box.php
Normal file
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* Example: Add a meta box to post editor
|
||||
*
|
||||
* This example shows how to:
|
||||
* - Register a meta box
|
||||
* - Render meta box fields
|
||||
* - Save meta box data securely
|
||||
* - Use nonces for CSRF protection
|
||||
* - Sanitize input and escape output
|
||||
*
|
||||
* @package YourPlugin
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta box
|
||||
*/
|
||||
function yourprefix_add_meta_box() {
|
||||
add_meta_box(
|
||||
'yourprefix_details', // Meta box ID
|
||||
__( 'Additional Details', 'your-plugin' ), // Title
|
||||
'yourprefix_render_meta_box', // Callback function
|
||||
'post', // Post type (or array of post types)
|
||||
'normal', // Context (normal, side, advanced)
|
||||
'high' // Priority
|
||||
);
|
||||
}
|
||||
add_action( 'add_meta_boxes', 'yourprefix_add_meta_box' );
|
||||
|
||||
/**
|
||||
* Render meta box content
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
function yourprefix_render_meta_box( $post ) {
|
||||
// Add nonce for security
|
||||
wp_nonce_field( 'yourprefix_save_meta', 'yourprefix_meta_nonce' );
|
||||
|
||||
// Get current values
|
||||
$text_value = get_post_meta( $post->ID, '_yourprefix_text', true );
|
||||
$number_value = get_post_meta( $post->ID, '_yourprefix_number', true );
|
||||
$select_value = get_post_meta( $post->ID, '_yourprefix_select', true );
|
||||
$checkbox = get_post_meta( $post->ID, '_yourprefix_checkbox', true );
|
||||
|
||||
?>
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th>
|
||||
<label for="yourprefix_text">
|
||||
<?php esc_html_e( 'Text Field', 'your-plugin' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="text"
|
||||
id="yourprefix_text"
|
||||
name="yourprefix_text"
|
||||
value="<?php echo esc_attr( $text_value ); ?>"
|
||||
class="regular-text"
|
||||
/>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Enter some text here', 'your-plugin' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<label for="yourprefix_number">
|
||||
<?php esc_html_e( 'Number Field', 'your-plugin' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="number"
|
||||
id="yourprefix_number"
|
||||
name="yourprefix_number"
|
||||
value="<?php echo esc_attr( $number_value ); ?>"
|
||||
min="0"
|
||||
max="100"
|
||||
class="small-text"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<label for="yourprefix_select">
|
||||
<?php esc_html_e( 'Select Field', 'your-plugin' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<select id="yourprefix_select" name="yourprefix_select">
|
||||
<option value=""><?php esc_html_e( '-- Select --', 'your-plugin' ); ?></option>
|
||||
<option value="option1" <?php selected( $select_value, 'option1' ); ?>>
|
||||
<?php esc_html_e( 'Option 1', 'your-plugin' ); ?>
|
||||
</option>
|
||||
<option value="option2" <?php selected( $select_value, 'option2' ); ?>>
|
||||
<?php esc_html_e( 'Option 2', 'your-plugin' ); ?>
|
||||
</option>
|
||||
<option value="option3" <?php selected( $select_value, 'option3' ); ?>>
|
||||
<?php esc_html_e( 'Option 3', 'your-plugin' ); ?>
|
||||
</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<?php esc_html_e( 'Checkbox', 'your-plugin' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="yourprefix_checkbox"
|
||||
name="yourprefix_checkbox"
|
||||
value="1"
|
||||
<?php checked( $checkbox, '1' ); ?>
|
||||
/>
|
||||
<?php esc_html_e( 'Enable this option', 'your-plugin' ); ?>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
function yourprefix_save_meta( $post_id, $post ) {
|
||||
// Verify nonce
|
||||
if ( ! isset( $_POST['yourprefix_meta_nonce'] ) ||
|
||||
! wp_verify_nonce( $_POST['yourprefix_meta_nonce'], 'yourprefix_save_meta' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check autosave
|
||||
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check user permissions
|
||||
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save text field
|
||||
if ( isset( $_POST['yourprefix_text'] ) ) {
|
||||
update_post_meta(
|
||||
$post_id,
|
||||
'_yourprefix_text',
|
||||
sanitize_text_field( $_POST['yourprefix_text'] )
|
||||
);
|
||||
}
|
||||
|
||||
// Save number field
|
||||
if ( isset( $_POST['yourprefix_number'] ) ) {
|
||||
update_post_meta(
|
||||
$post_id,
|
||||
'_yourprefix_number',
|
||||
absint( $_POST['yourprefix_number'] )
|
||||
);
|
||||
}
|
||||
|
||||
// Save select field
|
||||
if ( isset( $_POST['yourprefix_select'] ) ) {
|
||||
$allowed_values = array( 'option1', 'option2', 'option3' );
|
||||
$select_value = sanitize_text_field( $_POST['yourprefix_select'] );
|
||||
|
||||
// Validate against allowed values
|
||||
if ( in_array( $select_value, $allowed_values, true ) ) {
|
||||
update_post_meta( $post_id, '_yourprefix_select', $select_value );
|
||||
} else {
|
||||
delete_post_meta( $post_id, '_yourprefix_select' );
|
||||
}
|
||||
}
|
||||
|
||||
// Save checkbox
|
||||
if ( isset( $_POST['yourprefix_checkbox'] ) ) {
|
||||
update_post_meta( $post_id, '_yourprefix_checkbox', '1' );
|
||||
} else {
|
||||
delete_post_meta( $post_id, '_yourprefix_checkbox' );
|
||||
}
|
||||
}
|
||||
add_action( 'save_post', 'yourprefix_save_meta', 10, 2 );
|
||||
|
||||
/**
|
||||
* Display meta box data on frontend
|
||||
*
|
||||
* Add this to your theme's single.php or use a filter
|
||||
*/
|
||||
function yourprefix_display_meta_data( $content ) {
|
||||
if ( ! is_singular( 'post' ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
global $post;
|
||||
|
||||
$text_value = get_post_meta( $post->ID, '_yourprefix_text', true );
|
||||
$number_value = get_post_meta( $post->ID, '_yourprefix_number', true );
|
||||
$select_value = get_post_meta( $post->ID, '_yourprefix_select', true );
|
||||
$checkbox = get_post_meta( $post->ID, '_yourprefix_checkbox', true );
|
||||
|
||||
if ( $text_value || $number_value || $select_value || $checkbox ) {
|
||||
$meta_html = '<div class="custom-meta-data">';
|
||||
$meta_html .= '<h3>' . esc_html__( 'Additional Details', 'your-plugin' ) . '</h3>';
|
||||
$meta_html .= '<ul>';
|
||||
|
||||
if ( $text_value ) {
|
||||
$meta_html .= '<li><strong>' . esc_html__( 'Text:', 'your-plugin' ) . '</strong> ' . esc_html( $text_value ) . '</li>';
|
||||
}
|
||||
|
||||
if ( $number_value ) {
|
||||
$meta_html .= '<li><strong>' . esc_html__( 'Number:', 'your-plugin' ) . '</strong> ' . esc_html( $number_value ) . '</li>';
|
||||
}
|
||||
|
||||
if ( $select_value ) {
|
||||
$meta_html .= '<li><strong>' . esc_html__( 'Selection:', 'your-plugin' ) . '</strong> ' . esc_html( $select_value ) . '</li>';
|
||||
}
|
||||
|
||||
if ( $checkbox ) {
|
||||
$meta_html .= '<li><strong>' . esc_html__( 'Option enabled', 'your-plugin' ) . '</strong></li>';
|
||||
}
|
||||
|
||||
$meta_html .= '</ul>';
|
||||
$meta_html .= '</div>';
|
||||
|
||||
$content .= $meta_html;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
add_filter( 'the_content', 'yourprefix_display_meta_data' );
|
||||
384
templates/examples/rest-endpoint.php
Normal file
384
templates/examples/rest-endpoint.php
Normal file
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
/**
|
||||
* Example: REST API endpoints
|
||||
*
|
||||
* This example shows how to:
|
||||
* - Register custom REST API routes
|
||||
* - Implement GET, POST, PUT, DELETE endpoints
|
||||
* - Use permission callbacks for authentication
|
||||
* - Validate and sanitize request parameters
|
||||
* - Return proper REST responses and errors
|
||||
*
|
||||
* @package YourPlugin
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register REST API routes
|
||||
*/
|
||||
function yourprefix_register_rest_routes() {
|
||||
// Namespace: yourplugin/v1
|
||||
$namespace = 'yourplugin/v1';
|
||||
|
||||
// GET /wp-json/yourplugin/v1/items
|
||||
register_rest_route(
|
||||
$namespace,
|
||||
'/items',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => 'yourprefix_get_items',
|
||||
'permission_callback' => '__return_true', // Public endpoint
|
||||
)
|
||||
);
|
||||
|
||||
// GET /wp-json/yourplugin/v1/items/{id}
|
||||
register_rest_route(
|
||||
$namespace,
|
||||
'/items/(?P<id>\d+)',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => 'yourprefix_get_item',
|
||||
'permission_callback' => '__return_true',
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function( $param ) {
|
||||
return is_numeric( $param );
|
||||
},
|
||||
'sanitize_callback' => 'absint',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// POST /wp-json/yourplugin/v1/items
|
||||
register_rest_route(
|
||||
$namespace,
|
||||
'/items',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => 'yourprefix_create_item',
|
||||
'permission_callback' => 'yourprefix_check_permission',
|
||||
'args' => yourprefix_get_item_args(),
|
||||
)
|
||||
);
|
||||
|
||||
// PUT /wp-json/yourplugin/v1/items/{id}
|
||||
register_rest_route(
|
||||
$namespace,
|
||||
'/items/(?P<id>\d+)',
|
||||
array(
|
||||
'methods' => 'PUT',
|
||||
'callback' => 'yourprefix_update_item',
|
||||
'permission_callback' => 'yourprefix_check_permission',
|
||||
'args' => array_merge(
|
||||
array(
|
||||
'id' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function( $param ) {
|
||||
return is_numeric( $param );
|
||||
},
|
||||
'sanitize_callback' => 'absint',
|
||||
),
|
||||
),
|
||||
yourprefix_get_item_args()
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// DELETE /wp-json/yourplugin/v1/items/{id}
|
||||
register_rest_route(
|
||||
$namespace,
|
||||
'/items/(?P<id>\d+)',
|
||||
array(
|
||||
'methods' => 'DELETE',
|
||||
'callback' => 'yourprefix_delete_item',
|
||||
'permission_callback' => 'yourprefix_check_permission',
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function( $param ) {
|
||||
return is_numeric( $param );
|
||||
},
|
||||
'sanitize_callback' => 'absint',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'rest_api_init', 'yourprefix_register_rest_routes' );
|
||||
|
||||
/**
|
||||
* Get all items
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
function yourprefix_get_items( $request ) {
|
||||
// Get query parameters
|
||||
$per_page = $request->get_param( 'per_page' );
|
||||
$page = $request->get_param( 'page' );
|
||||
|
||||
// Set defaults
|
||||
$per_page = $per_page ? absint( $per_page ) : 10;
|
||||
$page = $page ? absint( $page ) : 1;
|
||||
|
||||
// Query posts
|
||||
$args = array(
|
||||
'post_type' => 'post',
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $page,
|
||||
'post_status' => 'publish',
|
||||
);
|
||||
|
||||
$query = new WP_Query( $args );
|
||||
|
||||
$items = array();
|
||||
foreach ( $query->posts as $post ) {
|
||||
$items[] = array(
|
||||
'id' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
'content' => $post->post_content,
|
||||
'excerpt' => $post->post_excerpt,
|
||||
'date' => $post->post_date,
|
||||
'author' => get_the_author_meta( 'display_name', $post->post_author ),
|
||||
);
|
||||
}
|
||||
|
||||
// Return response with pagination headers
|
||||
$response = rest_ensure_response( $items );
|
||||
$response->header( 'X-WP-Total', $query->found_posts );
|
||||
$response->header( 'X-WP-TotalPages', $query->max_num_pages );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single item
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
function yourprefix_get_item( $request ) {
|
||||
$item_id = $request->get_param( 'id' );
|
||||
$post = get_post( $item_id );
|
||||
|
||||
if ( ! $post ) {
|
||||
return new WP_Error(
|
||||
'not_found',
|
||||
__( 'Item not found', 'your-plugin' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'id' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
'content' => $post->post_content,
|
||||
'excerpt' => $post->post_excerpt,
|
||||
'date' => $post->post_date,
|
||||
'author' => get_the_author_meta( 'display_name', $post->post_author ),
|
||||
);
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create item
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
function yourprefix_create_item( $request ) {
|
||||
$title = $request->get_param( 'title' );
|
||||
$content = $request->get_param( 'content' );
|
||||
$status = $request->get_param( 'status' );
|
||||
|
||||
// Create post
|
||||
$post_id = wp_insert_post( array(
|
||||
'post_title' => $title,
|
||||
'post_content' => $content,
|
||||
'post_status' => $status ? $status : 'draft',
|
||||
'post_type' => 'post',
|
||||
) );
|
||||
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
$post = get_post( $post_id );
|
||||
|
||||
$data = array(
|
||||
'id' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
'content' => $post->post_content,
|
||||
'status' => $post->post_status,
|
||||
'date' => $post->post_date,
|
||||
);
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update item
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
function yourprefix_update_item( $request ) {
|
||||
$item_id = $request->get_param( 'id' );
|
||||
$post = get_post( $item_id );
|
||||
|
||||
if ( ! $post ) {
|
||||
return new WP_Error(
|
||||
'not_found',
|
||||
__( 'Item not found', 'your-plugin' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
// Update post
|
||||
$update_data = array(
|
||||
'ID' => $item_id,
|
||||
);
|
||||
|
||||
if ( $request->has_param( 'title' ) ) {
|
||||
$update_data['post_title'] = $request->get_param( 'title' );
|
||||
}
|
||||
|
||||
if ( $request->has_param( 'content' ) ) {
|
||||
$update_data['post_content'] = $request->get_param( 'content' );
|
||||
}
|
||||
|
||||
if ( $request->has_param( 'status' ) ) {
|
||||
$update_data['post_status'] = $request->get_param( 'status' );
|
||||
}
|
||||
|
||||
$result = wp_update_post( $update_data, true );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$post = get_post( $item_id );
|
||||
|
||||
$data = array(
|
||||
'id' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
'content' => $post->post_content,
|
||||
'status' => $post->post_status,
|
||||
'date' => $post->post_date,
|
||||
);
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
function yourprefix_delete_item( $request ) {
|
||||
$item_id = $request->get_param( 'id' );
|
||||
$post = get_post( $item_id );
|
||||
|
||||
if ( ! $post ) {
|
||||
return new WP_Error(
|
||||
'not_found',
|
||||
__( 'Item not found', 'your-plugin' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
// Delete post (move to trash)
|
||||
$result = wp_trash_post( $item_id );
|
||||
|
||||
if ( ! $result ) {
|
||||
return new WP_Error(
|
||||
'cannot_delete',
|
||||
__( 'Could not delete item', 'your-plugin' ),
|
||||
array( 'status' => 500 )
|
||||
);
|
||||
}
|
||||
|
||||
return rest_ensure_response( array(
|
||||
'deleted' => true,
|
||||
'id' => $item_id,
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check permission
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function yourprefix_check_permission() {
|
||||
return current_user_can( 'edit_posts' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item validation arguments
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function yourprefix_get_item_args() {
|
||||
return array(
|
||||
'title' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'description' => __( 'Item title', 'your-plugin' ),
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'content' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'description' => __( 'Item content', 'your-plugin' ),
|
||||
'sanitize_callback' => 'wp_kses_post',
|
||||
),
|
||||
'status' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'description' => __( 'Item status', 'your-plugin' ),
|
||||
'enum' => array( 'publish', 'draft', 'pending', 'private' ),
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example AJAX endpoint (alternative to REST API for simpler use cases)
|
||||
*/
|
||||
function yourprefix_ajax_get_items() {
|
||||
// Verify nonce
|
||||
check_ajax_referer( 'yourprefix_nonce', 'nonce' );
|
||||
|
||||
// Check permission
|
||||
if ( ! current_user_can( 'edit_posts' ) ) {
|
||||
wp_send_json_error( array( 'message' => __( 'Permission denied', 'your-plugin' ) ) );
|
||||
}
|
||||
|
||||
// Get items
|
||||
$args = array(
|
||||
'post_type' => 'post',
|
||||
'posts_per_page' => 10,
|
||||
'post_status' => 'publish',
|
||||
);
|
||||
|
||||
$query = new WP_Query( $args );
|
||||
|
||||
$items = array();
|
||||
foreach ( $query->posts as $post ) {
|
||||
$items[] = array(
|
||||
'id' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json_success( array( 'items' => $items ) );
|
||||
}
|
||||
add_action( 'wp_ajax_yourprefix_get_items', 'yourprefix_ajax_get_items' );
|
||||
308
templates/examples/settings-page.php
Normal file
308
templates/examples/settings-page.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
/**
|
||||
* Example: Settings page using WordPress Settings API
|
||||
*
|
||||
* This example shows how to:
|
||||
* - Add a settings page to WordPress admin
|
||||
* - Register settings with Settings API
|
||||
* - Add settings sections and fields
|
||||
* - Sanitize and validate settings
|
||||
* - Use different field types
|
||||
*
|
||||
* @package YourPlugin
|
||||
*/
|
||||
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings page to admin menu
|
||||
*/
|
||||
function yourprefix_add_settings_page() {
|
||||
add_options_page(
|
||||
__( 'Your Plugin Settings', 'your-plugin' ), // Page title
|
||||
__( 'Your Plugin', 'your-plugin' ), // Menu title
|
||||
'manage_options', // Capability
|
||||
'your-plugin-settings', // Menu slug
|
||||
'yourprefix_render_settings_page' // Callback function
|
||||
);
|
||||
}
|
||||
add_action( 'admin_menu', 'yourprefix_add_settings_page' );
|
||||
|
||||
/**
|
||||
* Register settings
|
||||
*/
|
||||
function yourprefix_register_settings() {
|
||||
// Register setting
|
||||
register_setting(
|
||||
'yourprefix_settings_group', // Option group
|
||||
'yourprefix_settings', // Option name
|
||||
'yourprefix_sanitize_settings' // Sanitize callback
|
||||
);
|
||||
|
||||
// Add settings section
|
||||
add_settings_section(
|
||||
'yourprefix_general_section', // Section ID
|
||||
__( 'General Settings', 'your-plugin' ), // Section title
|
||||
'yourprefix_general_section_callback', // Callback
|
||||
'your-plugin-settings' // Page slug
|
||||
);
|
||||
|
||||
// Add settings fields
|
||||
add_settings_field(
|
||||
'yourprefix_text_field',
|
||||
__( 'Text Field', 'your-plugin' ),
|
||||
'yourprefix_text_field_callback',
|
||||
'your-plugin-settings',
|
||||
'yourprefix_general_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'yourprefix_number_field',
|
||||
__( 'Number Field', 'your-plugin' ),
|
||||
'yourprefix_number_field_callback',
|
||||
'your-plugin-settings',
|
||||
'yourprefix_general_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'yourprefix_checkbox_field',
|
||||
__( 'Checkbox Field', 'your-plugin' ),
|
||||
'yourprefix_checkbox_field_callback',
|
||||
'your-plugin-settings',
|
||||
'yourprefix_general_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'yourprefix_select_field',
|
||||
__( 'Select Field', 'your-plugin' ),
|
||||
'yourprefix_select_field_callback',
|
||||
'your-plugin-settings',
|
||||
'yourprefix_general_section'
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
'yourprefix_textarea_field',
|
||||
__( 'Textarea Field', 'your-plugin' ),
|
||||
'yourprefix_textarea_field_callback',
|
||||
'your-plugin-settings',
|
||||
'yourprefix_general_section'
|
||||
);
|
||||
}
|
||||
add_action( 'admin_init', 'yourprefix_register_settings' );
|
||||
|
||||
/**
|
||||
* Render settings page
|
||||
*/
|
||||
function yourprefix_render_settings_page() {
|
||||
// Check user capabilities
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show success message if settings were saved
|
||||
if ( isset( $_GET['settings-updated'] ) ) {
|
||||
add_settings_error(
|
||||
'yourprefix_messages',
|
||||
'yourprefix_message',
|
||||
__( 'Settings Saved', 'your-plugin' ),
|
||||
'updated'
|
||||
);
|
||||
}
|
||||
|
||||
// Show error/update messages
|
||||
settings_errors( 'yourprefix_messages' );
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields( 'yourprefix_settings_group' );
|
||||
do_settings_sections( 'your-plugin-settings' );
|
||||
submit_button( __( 'Save Settings', 'your-plugin' ) );
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Section callback
|
||||
*/
|
||||
function yourprefix_general_section_callback() {
|
||||
echo '<p>' . esc_html__( 'Configure your plugin settings below.', 'your-plugin' ) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings with defaults
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function yourprefix_get_settings() {
|
||||
$defaults = array(
|
||||
'text_field' => '',
|
||||
'number_field' => 0,
|
||||
'checkbox_field' => false,
|
||||
'select_field' => '',
|
||||
'textarea_field' => '',
|
||||
);
|
||||
|
||||
$settings = get_option( 'yourprefix_settings', $defaults );
|
||||
|
||||
return wp_parse_args( $settings, $defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Text field callback
|
||||
*/
|
||||
function yourprefix_text_field_callback() {
|
||||
$settings = yourprefix_get_settings();
|
||||
$value = $settings['text_field'];
|
||||
|
||||
printf(
|
||||
'<input type="text" id="yourprefix_text_field" name="yourprefix_settings[text_field]" value="%s" class="regular-text" />',
|
||||
esc_attr( $value )
|
||||
);
|
||||
echo '<p class="description">' . esc_html__( 'Enter some text here', 'your-plugin' ) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Number field callback
|
||||
*/
|
||||
function yourprefix_number_field_callback() {
|
||||
$settings = yourprefix_get_settings();
|
||||
$value = $settings['number_field'];
|
||||
|
||||
printf(
|
||||
'<input type="number" id="yourprefix_number_field" name="yourprefix_settings[number_field]" value="%s" min="0" max="100" class="small-text" />',
|
||||
esc_attr( $value )
|
||||
);
|
||||
echo '<p class="description">' . esc_html__( 'Enter a number between 0 and 100', 'your-plugin' ) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkbox field callback
|
||||
*/
|
||||
function yourprefix_checkbox_field_callback() {
|
||||
$settings = yourprefix_get_settings();
|
||||
$value = $settings['checkbox_field'];
|
||||
|
||||
printf(
|
||||
'<input type="checkbox" id="yourprefix_checkbox_field" name="yourprefix_settings[checkbox_field]" value="1" %s />',
|
||||
checked( $value, true, false )
|
||||
);
|
||||
echo '<label for="yourprefix_checkbox_field">' . esc_html__( 'Enable this feature', 'your-plugin' ) . '</label>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Select field callback
|
||||
*/
|
||||
function yourprefix_select_field_callback() {
|
||||
$settings = yourprefix_get_settings();
|
||||
$value = $settings['select_field'];
|
||||
|
||||
?>
|
||||
<select id="yourprefix_select_field" name="yourprefix_settings[select_field]">
|
||||
<option value=""><?php esc_html_e( '-- Select --', 'your-plugin' ); ?></option>
|
||||
<option value="option1" <?php selected( $value, 'option1' ); ?>>
|
||||
<?php esc_html_e( 'Option 1', 'your-plugin' ); ?>
|
||||
</option>
|
||||
<option value="option2" <?php selected( $value, 'option2' ); ?>>
|
||||
<?php esc_html_e( 'Option 2', 'your-plugin' ); ?>
|
||||
</option>
|
||||
<option value="option3" <?php selected( $value, 'option3' ); ?>>
|
||||
<?php esc_html_e( 'Option 3', 'your-plugin' ); ?>
|
||||
</option>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Textarea field callback
|
||||
*/
|
||||
function yourprefix_textarea_field_callback() {
|
||||
$settings = yourprefix_get_settings();
|
||||
$value = $settings['textarea_field'];
|
||||
|
||||
printf(
|
||||
'<textarea id="yourprefix_textarea_field" name="yourprefix_settings[textarea_field]" rows="5" cols="50" class="large-text">%s</textarea>',
|
||||
esc_textarea( $value )
|
||||
);
|
||||
echo '<p class="description">' . esc_html__( 'Enter some longer text here', 'your-plugin' ) . '</p>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize settings
|
||||
*
|
||||
* @param array $input Input array.
|
||||
* @return array Sanitized array.
|
||||
*/
|
||||
function yourprefix_sanitize_settings( $input ) {
|
||||
$sanitized = array();
|
||||
|
||||
// Text field
|
||||
if ( isset( $input['text_field'] ) ) {
|
||||
$sanitized['text_field'] = sanitize_text_field( $input['text_field'] );
|
||||
}
|
||||
|
||||
// Number field
|
||||
if ( isset( $input['number_field'] ) ) {
|
||||
$number = absint( $input['number_field'] );
|
||||
|
||||
// Validate range
|
||||
if ( $number < 0 || $number > 100 ) {
|
||||
add_settings_error(
|
||||
'yourprefix_messages',
|
||||
'yourprefix_message',
|
||||
__( 'Number must be between 0 and 100', 'your-plugin' ),
|
||||
'error'
|
||||
);
|
||||
$sanitized['number_field'] = 0;
|
||||
} else {
|
||||
$sanitized['number_field'] = $number;
|
||||
}
|
||||
}
|
||||
|
||||
// Checkbox field
|
||||
if ( isset( $input['checkbox_field'] ) ) {
|
||||
$sanitized['checkbox_field'] = true;
|
||||
} else {
|
||||
$sanitized['checkbox_field'] = false;
|
||||
}
|
||||
|
||||
// Select field
|
||||
if ( isset( $input['select_field'] ) ) {
|
||||
$allowed_values = array( 'option1', 'option2', 'option3' );
|
||||
$select_value = sanitize_text_field( $input['select_field'] );
|
||||
|
||||
// Validate against allowed values
|
||||
if ( in_array( $select_value, $allowed_values, true ) ) {
|
||||
$sanitized['select_field'] = $select_value;
|
||||
} else {
|
||||
$sanitized['select_field'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// Textarea field
|
||||
if ( isset( $input['textarea_field'] ) ) {
|
||||
$sanitized['textarea_field'] = sanitize_textarea_field( $input['textarea_field'] );
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific setting value
|
||||
*
|
||||
* @param string $key Setting key.
|
||||
* @param mixed $default Default value.
|
||||
* @return mixed Setting value or default.
|
||||
*/
|
||||
function yourprefix_get_setting( $key, $default = '' ) {
|
||||
$settings = yourprefix_get_settings();
|
||||
|
||||
return isset( $settings[ $key ] ) ? $settings[ $key ] : $default;
|
||||
}
|
||||
Reference in New Issue
Block a user