Skip to content

Documenation

Ali Barzegar edited this page Aug 28, 2026 · 1 revision

wpint/wpapi — Usage

Every object below is a fluent builder: chain setters, then call ->register(). Each one wraps ->register() in whatever WordPress lifecycle hook it actually needs (init, admin_init, widgets_init, ...), so you can safely call ->register() at any point during your plugin's bootstrap — you don't need to wrap the call yourself.

use Wpint\WPAPI\WPAPI;

Hook

Register a plain add_action/add_filter hook.

use Wpint\WPAPI\Hook\Enum\HookTypeEnum;

WPAPI::hook()
    ->name('save_post')
    ->type(HookTypeEnum::ACTION)
    ->callback(fn($post_id) => error_log("Post {$post_id} saved"))
    ->priority(10)
    ->acceptedArgs(1)
    ->register();

Cron

Schedule a recurring cron event. every() accepts any interval slug — a built-in one (Cron\Enum\CronIntervalEnum) or a custom one registered via Cron::addCronInterval().

use Wpint\WPAPI\Cron\Cron;
use Wpint\WPAPI\Cron\Enum\CronIntervalEnum;

Cron::addCronInterval('every_five_minutes', 5 * MINUTE_IN_SECONDS, 'Every 5 Minutes');

WPAPI::cron()
    ->name('wpint_cleanup_temp_files')
    ->execute(fn() => wpint_delete_expired_temp_files())
    ->start(time())
    ->every('every_five_minutes')
    ->register();

Cron::addCronInterval() internally builds a Wpint\WPAPI\Cron\CronInterval object for you — you won't normally construct CronInterval directly.

Metabox

Renders a meta box and safely saves its value. A nonce field is emitted automatically, and the save handler verifies the nonce, checks current_user_can(), skips autosaves, and sanitizes the posted value (sanitize_text_field by default) before saving — you don't need to add any of that yourself.

WPAPI::metabox()
    ->id('wpint_subtitle')
    ->title('Subtitle')
    ->screen('post')
    ->metaKey('wpint_subtitle')
    ->postKey('wpint_subtitle_field')
    ->callback(function (array $args) {
        $value = get_post_meta($args['post']->ID, 'wpint_subtitle', true);
        printf('<input type="text" name="wpint_subtitle_field" value="%s" />', esc_attr($value));
    })
    ->register();

PostType

use Wpint\WPAPI\PostType\Enum\PostTypeSupportsEnum;

WPAPI::postType()
    ->name('book')
    ->singularName('Book')
    ->public(true)
    ->showUI(true)
    ->hasArchive(true)
    ->showInRest(true)
    ->supports(PostTypeSupportsEnum::TITLE, PostTypeSupportsEnum::EDITOR, PostTypeSupportsEnum::THUMBNAIL)
    ->register();

Taxonomy

use Wpint\WPAPI\Taxonomy\Enum\TaxonomyCapabilitiesEnum;

WPAPI::taxonomy()
    ->name('genre')
    ->postType('book')
    ->hierarchical(true)
    ->showUI(true)
    ->showInRest(true)
    ->capabilities(TaxonomyCapabilitiesEnum::MANAGE_TERMS, TaxonomyCapabilitiesEnum::ASSIGN_TERMS)
    ->register();

Setting

Registers an option along with its settings-API section/field. sanitizeCallback() defaults to sanitize_text_field — WordPress core applies no sanitizer by default, which this closes.

WPAPI::setting()
    ->name('wpint_support_email')
    ->optionGroup('general')
    ->type('string')
    ->default('support@example.com')
    ->sectionTitle('Support')
    ->sectionCallback(fn() => print('<p>Contact details shown on the front end.</p>'))
    ->fieldtitle('Support email')
    ->fieldCallback(fn() => printf(
        '<input type="email" name="wpint_support_email" value="%s" />',
        esc_attr(get_option('wpint_support_email'))
    ))
    ->register();

Shortcode

WPAPI::shortcode()
    ->tag('wpint_year')
    ->callback(fn(array $attrs, ?string $content) => esc_html(date('Y')))
    ->register();

Enqueuer

Queue one or more scripts/styles. version defaults to the file's own filemtime() for automatic cache-busting when you deploy.

use Wpint\WPAPI\Enqueuer\Enum\EnqueuerScopeEnum;

WPAPI::enqueuer()
    ->scope(EnqueuerScopeEnum::CLIENT)
    ->js('assets/app.js', deps: ['jquery'], inFooter: true)
    ->css('assets/app.css')
    ->register();

PostMeta

The proper, secure alternative to hand-rolling meta storage in a save_post handler — wraps register_post_meta(). sanitizeCallback() defaults to sanitize_text_field.

WPAPI::postMeta()
    ->postType('book')
    ->key('isbn')
    ->type('string')
    ->single(true)
    ->showInRest(true)
    ->register();

RestRoute

Security default: if you never call permissionCallback() (or public()), the route denies every request. This avoids the common __return_true footgun.

WPAPI::restRoute()
    ->namespace('wpint/v1')
    ->route('/books/(?P<id>\d+)')
    ->methods('GET')
    ->callback(fn(\WP_REST_Request $request) => rest_ensure_response(
        get_post($request->get_param('id'))
    ))
    ->permissionCallback(fn() => current_user_can('read'))
    ->register();

Ajax

Security default: a check_ajax_referer() nonce check runs automatically before your callback, and the handler is logged-in-only unless you call public().

WPAPI::ajax()
    ->action('wpint_refresh_widget')
    ->nonce('wpint_refresh_widget')
    ->callback(fn() => wp_send_json_success(['html' => wpint_render_widget()]))
    ->register();

ImageSize

WPAPI::imageSize()
    ->name('wpint-card')
    ->width(400)
    ->height(300)
    ->crop(true)
    ->label('Card')
    ->showInDropdown(true)
    ->register();

Sidebar

WPAPI::sidebar()
    ->name('Footer Widgets')
    ->id('footer-widgets')
    ->description('Widgets shown in the site footer.')
    ->register();

NavMenu

WPAPI::navMenu()
    ->location('primary', 'Primary Menu')
    ->location('footer', 'Footer Menu')
    ->register();

Role

Capability lists must always be a static, developer-defined whitelist — never build them from user-controlled input.

WPAPI::role()
    ->name('book_editor')
    ->displayName('Book Editor')
    ->extends('editor')
    ->capabilities('edit_books', 'publish_books', 'delete_books')
    ->register();

Clone this wiki locally