bitshost / quickwp
QuickWP โ A modern PHP toolkit for managing WordPress sites via the REST API. Provides clean OOP architecture, multi-site support, and ready-to-use web tools for posts, pages, media, taxonomies, and custom post types.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:project
pkg:composer/bitshost/quickwp
Requires
- php: >=7.4
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.6
README
QuickWP is a modern, class-based PHP toolkit for managing WordPress sites via the REST API. It provides both a clean programmatic API and ready-to-use web tools for common WordPress operations.
๐ฆ Installation
composer require bitshost/quickwp
๐ Requirements
- PHP 7.4+
- WordPress site with REST API enabled
- WordPress Application Password for authentication
โจ Features
- Clean OOP Architecture โ PSR-4 autoloaded classes with dependency injection
- Fluent API โ Intuitive, chainable interface for all operations
- Multi-Site Support โ Manage multiple WordPress sites from one installation
- Web UI Tools โ Ready-to-use forms for posts, pages, media, taxonomies, and CPTs
- Flexible Access Control โ HTTP Basic Auth, token auth, or no protection
- Service-Based Design โ Separate services for Posts, Pages, Media, Taxonomies, and CPTs
๐ Project Structure
QuickWP/
โโโ src/ # Core library (PSR-4: QuickWP\)
โ โโโ QuickWP.php # Main facade class
โ โโโ Bootstrap.php # Factory for service creation
โ โโโ Config/
โ โ โโโ Config.php # Base immutable config wrapper
โ โ โโโ ConfigLoader.php # Loads config from files
โ โ โโโ SiteConfig.php # Site-specific configuration
โ โโโ Http/
โ โ โโโ AccessControl.php # Access control middleware
โ โ โโโ RestClient.php # cURL-based REST client
โ โโโ Service/
โ โโโ PostService.php # Post CRUD operations
โ โโโ PageService.php # Page CRUD operations
โ โโโ CptService.php # Custom Post Type operations
โ โโโ MediaService.php # Media upload & management
โ โโโ MenuService.php # Menu operations
โ โโโ TaxonomyService.php # Categories/Tags management
โ โโโ TemplateService.php # Template fetching
โโโ public/ # Web interface
โ โโโ index.php # Dashboard
โ โโโ quick-post.php # Create/edit posts
โ โโโ quick-page.php # Create/edit pages
โ โโโ quick-media.php # Upload media
โ โโโ quick-cpt.php # Custom post types
โ โโโ quick-edit.php # Edit by ID
โ โโโ quick-taxonomy.php # Categories/Tags
โ โโโ quick-wp.php # Legacy entry point
โโโ tests/ # PHPUnit tests
โโโ quick-config.php # Your site configuration
โโโ quick-sites.php # Multi-site configuration (optional)
โโโ composer.json # PSR-4 autoloader
๐ Quick Start
1. Install via Composer
composer require bitshost/quickwp
Or clone the repository and run composer install.
2. Configure Your Site
Copy the example config and edit with your WordPress site details:
cp quick-config.example.php quick-config.php
<?php return [ // REST API Endpoints 'posts_endpoint' => 'https://your-site.com/wp-json/wp/v2/posts', 'pages_endpoint' => 'https://your-site.com/wp-json/wp/v2/pages', 'media_endpoint' => 'https://your-site.com/wp-json/wp/v2/media', // WordPress Credentials (Application Password) 'wp_username' => 'your-username', 'wp_app_password' => 'xxxx xxxx xxxx xxxx xxxx xxxx', // Options 'show_auth_form' => true, // Show credentials in forms 'verify_ssl' => true, // Verify SSL certificates 'debug_http' => false, // Debug cURL requests ];
3. Create an Application Password
- Log in to your WordPress admin
- Go to Users โ Profile โ Application Passwords
- Enter a name (e.g., "QuickWP") and click Add New
- Copy the generated password to your
quick-config.php
4. Access the Web Interface
Point your browser to public/index.php
๐ป Programmatic Usage
Basic Example
<?php require_once __DIR__ . '/vendor/autoload.php'; use QuickWP\QuickWP; // Initialize with config directory $qwp = QuickWP::init(__DIR__); // Create a post $result = $qwp->posts()->create([ 'title' => 'My New Post', 'content' => '<p>Hello from QuickWP!</p>', 'status' => 'draft', ]); if (QuickWP::isSuccess($result)) { echo 'Post created! ID: ' . QuickWP::getId($result); echo 'Link: ' . QuickWP::getLink($result); } else { echo 'Error: ' . QuickWP::getError($result); }
Using Services
// Posts $posts = $qwp->posts(); $posts->create(['title' => 'New Post', 'status' => 'publish']); $posts->update(123, ['title' => 'Updated Title']); $posts->get(123); $posts->list(['per_page' => 10, 'status' => 'draft']); $posts->delete(123, force: true); // Pages $pages = $qwp->pages(); $pages->create(['title' => 'New Page', 'parent' => 0, 'template' => 'full-width.php']); // Media $media = $qwp->media(); $media->upload($_FILES['file'], ['title' => 'My Image', 'alt_text' => 'Alt text']); $media->setFeaturedImage(postId: 123, mediaId: 456); // Taxonomies $tax = $qwp->taxonomy(); $tax->createCategory(['name' => 'News', 'slug' => 'news']); $tax->createTag(['name' => 'Featured']); $tax->listCategories(['hide_empty' => false]); // Custom Post Types $cpt = $qwp->cpt(); $cpt->create('product', ['title' => 'New Product', 'status' => 'publish']); $cpt->list('product', ['per_page' => 20]);
Alternative Initialization
// From explicit config array $qwp = QuickWP::withConfig([ 'posts_endpoint' => 'https://example.com/wp-json/wp/v2/posts', 'wp_username' => 'admin', 'wp_app_password' => 'xxxx xxxx xxxx', ]); // With specific site from multi-site config $qwp = QuickWP::init(__DIR__, siteKey: 'staging'); // Without access control enforcement $qwp = QuickWP::init(__DIR__, enforceAccess: false);
๐ API Reference
QuickWP Facade
| Method | Description |
|---|---|
QuickWP::init($baseDir, $siteKey, $enforceAccess) |
Initialize from config files |
QuickWP::withConfig($array) |
Initialize with explicit config |
$qwp->posts() |
Get PostService instance |
$qwp->pages() |
Get PageService instance |
$qwp->cpt() |
Get CptService instance |
$qwp->media() |
Get MediaService instance |
$qwp->taxonomy() |
Get TaxonomyService instance |
$qwp->menus() |
Get MenuService instance |
$qwp->templates() |
Get TemplateService instance |
$qwp->getConfig() |
Get current SiteConfig |
$qwp->getClient() |
Get RestClient instance |
Static Helpers
| Method | Description |
|---|---|
QuickWP::isSuccess($result) |
Check if operation succeeded |
QuickWP::getError($result) |
Get error message from result |
QuickWP::getId($result) |
Get created/updated item ID |
QuickWP::getLink($result) |
Get item URL/link |
Shortcut Methods
$qwp->createPost($data); // Create a post $qwp->createPage($data); // Create a page $qwp->createCptItem($slug, $data); // Create CPT item $qwp->uploadMedia($fileInfo, $data); // Upload media $qwp->createCategory($data); // Create category $qwp->createTag($data); // Create tag
Service Methods
Each service follows a consistent CRUD pattern:
$service->create($data); // Create item $service->update($id, $data); // Update item $service->get($id); // Get single item $service->list($params); // List items with filters $service->delete($id, $force); // Delete item
๐ Multi-Site Configuration
Create quick-sites.php to manage multiple WordPress sites:
<?php return [ 'default_site' => 'production', 'sites' => [ 'production' => [ 'label' => 'Production Site', 'posts_endpoint' => 'https://example.com/wp-json/wp/v2/posts', 'pages_endpoint' => 'https://example.com/wp-json/wp/v2/pages', 'media_endpoint' => 'https://example.com/wp-json/wp/v2/media', 'wp_username' => 'prod-admin', 'wp_app_password' => 'xxxx xxxx xxxx xxxx', ], 'staging' => [ 'label' => 'Staging Site', 'posts_endpoint' => 'https://staging.example.com/wp-json/wp/v2/posts', 'pages_endpoint' => 'https://staging.example.com/wp-json/wp/v2/pages', 'media_endpoint' => 'https://staging.example.com/wp-json/wp/v2/media', 'wp_username' => 'staging-admin', 'wp_app_password' => 'yyyy yyyy yyyy yyyy', ], ], ];
Switch sites via URL parameter: ?site=staging
Or programmatically:
$qwp = QuickWP::init(__DIR__, siteKey: 'staging');
๐ Access Control
Configure access protection in quick-config.php:
// No protection (default) 'access_mode' => 'none', // HTTP Basic Auth 'access_mode' => 'basic', 'access_basic_user' => 'admin', 'access_basic_password' => 'secret-password', // Token in URL 'access_mode' => 'token', 'access_token' => 'my-secret-token', // Access via: ?token=my-secret-token
โ๏ธ Configuration Reference
| Key | Type | Default | Description |
|---|---|---|---|
posts_endpoint |
string | '' |
WordPress posts REST endpoint |
pages_endpoint |
string | '' |
WordPress pages REST endpoint |
media_endpoint |
string | '' |
WordPress media REST endpoint |
categories_endpoint |
string | derived | Categories endpoint (auto-derived if empty) |
tags_endpoint |
string | derived | Tags endpoint (auto-derived if empty) |
wp_username |
string | '' |
WordPress username |
wp_app_password |
string | '' |
WordPress Application Password |
verify_ssl |
bool | true |
Verify SSL certificates |
debug_http |
bool | false |
Show cURL debug info |
show_auth_form |
bool | true |
Show credentials in web forms |
access_mode |
string | 'none' |
Access control: none, basic, or token |
access_basic_user |
string | '' |
HTTP Basic Auth username |
access_basic_password |
string | '' |
HTTP Basic Auth password |
access_token |
string | '' |
URL token for token auth |
cpt_default_slug |
string | 'post' |
Default custom post type slug |
page_templates |
array | [] |
Available page templates |
post_templates |
array | [] |
Available post templates |
๐ง Response Format
All service methods return a standardized response array:
[
'ok' => true, // Success flag
'http_code' => 201, // HTTP status code
'json' => [...], // Decoded JSON response
'raw_body' => '...', // Raw response body
'curl_error' => null, // cURL error message (if any)
'info' => [...], // cURL info array
'headers' => [...], // Response headers
]
๐ก๏ธ Security Best Practices
- Never commit credentials โ Keep
quick-config.phpandquick-sites.phpout of version control - Use Application Passwords โ Don't use your WordPress login password
- Enable SSL verification โ Keep
verify_ssl => truein production - Protect the tools folder โ Use
access_mode, HTTP auth, or IP restrictions - Use minimal permissions โ Create WordPress users with only the capabilities needed
- Revoke leaked passwords โ If credentials are exposed, revoke them immediately in WordPress
๐ Requirements
- PHP 7.4 or higher
- cURL extension
- WordPress 5.6+ (for Application Passwords)
- WordPress REST API enabled
๐งช Development
# Run tests composer test # Static analysis composer analyse
๐ License
MIT License โ see LICENSE for details.