arraypress/wp-inline-sync

Lightweight WordPress library for inline batch sync operations with progress UI. Register sync operations that run directly on existing admin screens.

Installs: 7

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/arraypress/wp-inline-sync

dev-main 2026-02-21 12:44 UTC

This package is auto-updated.

Last update: 2026-02-21 12:44:28 UTC


README

A lightweight WordPress library for inline batch sync operations with progress UI. Register sync operations that run directly on existing admin screens — no separate pages, no stats storage, no complexity.

Features

  • Inline progress bar — renders above your admin table with real-time progress
  • Current item display — shows the name of each item as it's processed
  • Auto-binding buttons — output a trigger button, the JS handles everything
  • Single REST endpoint — one endpoint serves all registered syncs
  • Cursor-based pagination — works with any API that supports cursor pagination
  • Cancel support — users can cancel mid-sync
  • Dismissable notices — completion summary disappears on click or page refresh
  • No persistence — nothing stored in the database, refresh and it's gone

Requirements

  • PHP 8.1+
  • WordPress 6.0+

Installation

composer require arraypress/wp-inline-sync

Quick Start

1. Register a sync

register_sync( 'stripe_prices', [
    'hook_suffix'      => 'toplevel_page_sugarcart',
    'title'            => __( 'Sync Prices', 'my-plugin' ),
    'button_label'     => __( 'Sync from Stripe', 'my-plugin' ),
    'container'        => '.wp-list-table',
    'data_callback'    => 'MyPlugin\fetch_prices',
    'process_callback' => 'MyPlugin\process_price',
    'name_callback'    => fn( $item ) => $item->product->name ?? $item->id,
] );

2. Output the trigger button

// In your admin screen
render_sync_button( 'stripe_prices' );

That's it. The button renders with data attributes, the JS auto-binds on click, and the progress bar appears above your table.

Configuration

Key Type Default Description
hook_suffix string|array '' Admin screen hook suffix(es) where assets should load.
capability string 'manage_options' Required user capability.
title string '' Display title shown in the progress bar header.
button_label string 'Sync' Text for the trigger button.
button_class string 'button' CSS class(es) for the trigger button.
container string '.wp-list-table' CSS selector — progress bar inserts before this element.
data_callback callable null Fetches items. Receives (string $cursor).
process_callback callable null Processes one item.
name_callback callable|null null Extracts a display name from an item.

Callbacks

data_callback

Fetches a batch of items from your data source. Receives the cursor string (empty on first call). You control the batch size internally.

function fetch_prices( string $cursor ): array {
    $params = [
        'limit'  => 100,
        'active' => true,
    ];

    if ( $cursor ) {
        $params['starting_after'] = $cursor;
    }

    $prices = $stripe->prices->all( $params );
    $last   = end( $prices->data );

    return [
        'items'    => $prices->data,
        'has_more' => $prices->has_more,
        'cursor'   => $last ? $last->id : '',
        'total'    => null, // null if unknown
    ];
}

Return format:

Key Type Description
items array Items to process this batch.
has_more bool Whether more batches remain.
cursor string Cursor to pass on next call.
total int|null Total item count if known (enables % progress).

process_callback

Processes a single item. Called once per item in the batch.

function process_price( object $item ): string|WP_Error {
    $existing = get_price_by_stripe_id( $item->id );

    if ( $existing ) {
        update_price( $existing->id, [ /* ... */ ] );
        return 'updated';
    }

    add_price( [ /* ... */ ] );
    return 'created';
}

Return values:

Value Meaning
'created' Item was newly created
'updated' Item was updated
'skipped' Item was skipped
WP_Error Item failed

name_callback

Optional. Extracts a display name from an item for the progress UI. If not provided, the library guesses by checking common fields (name, title, label, email, id).

'name_callback' => fn( $item ) => $item->product->name ?? $item->id,

Functions

register_sync

register_sync( string $id, array $config ): Sync

Register an inline sync operation.

get_sync

get_sync( string $id ): ?Sync

Retrieve a registered sync instance.

has_sync

has_sync( string $id ): bool

Check if a sync is registered.

render_sync_button

render_sync_button( string $id, array $args = [] ): void

Output a trigger button. Accepts optional overrides for label, class, and container.

get_sync_button

get_sync_button( string $id, array $args = [] ): string

Returns the button HTML instead of echoing it.

JavaScript API

The JS auto-binds to .inline-sync-trigger buttons. For programmatic control:

// Start a sync manually
InlineSync.start('stripe_prices');

// Cancel a running sync
InlineSync.cancel('stripe_prices');

Events

Events are fired on $(document):

Event Arguments Description
inline-sync:complete syncId, totals Sync finished
inline-sync:cancelled syncId User cancelled
inline-sync:error syncId, message Sync failed
$(document).on('inline-sync:complete', function (e, syncId, totals) {
    if (syncId === 'stripe_prices') {
        // Reload the table
        location.reload();
    }
});

Multiple Syncs

Register each sync separately. They can target the same screen:

register_sync( 'stripe_prices', [
    'hook_suffix'      => 'toplevel_page_my-plugin',
    'title'            => 'Sync Prices',
    'button_label'     => 'Sync Prices',
    'data_callback'    => 'fetch_prices',
    'process_callback' => 'process_price',
] );

register_sync( 'stripe_customers', [
    'hook_suffix'      => 'my-plugin_page_customers',
    'title'            => 'Sync Customers',
    'button_label'     => 'Sync Customers',
    'data_callback'    => 'fetch_customers',
    'process_callback' => 'process_customer',
] );

Progress Bar Behavior

During sync: Blue left border, progress track with fill, item count, current item name, cancel button.

On completion: Green left border, summary line (e.g., "120 items synced — 3 created, 115 updated, 2 skipped"), dismiss button. First 3 error messages shown inline if any items failed.

On error/cancel: Red left border, error message or "Sync cancelled", dismiss button.

On dismiss or page refresh: Gone. Nothing persisted.

License

GPL-2.0-or-later