Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/appsdevpk/adpcoreplugin/archive/refs/heads/main.zipAdpCore - WordPress Plugin Framework
A comprehensive WordPress plugin framework that supercharges your development workflow with Blade templating, web components, custom post types, conditionals, and much more — all configurable through simple JSON files.
Version: 2.0.0
Requires PHP: 7.4+
License: GPL-2.0-or-later
Table of Contents
- Installation
- Quick Start
- App Folder Structure
- Features
- Built-in Shortcodes Reference
- Event Hooks System
- Namespaced Classes
- Backward Compatibility
- Security Features
- Architecture
Installation
-
Install the Plugin
Clone or download this repository into your WordPress
wp-content/plugins/directory:wp-content/plugins/adpcore/ -
Install Dependencies
cd wp-content/plugins/adpcore composer install -
Copy the App Folder
Copy the
AdpAppfolder to your active theme directory:wp-content/themes/your-active-theme/AdpApp/ -
Activate the Plugin
Go to WordPress Admin → Plugins and activate Adp Core.
-
Start Using
Navigate to Adp Tools in the WordPress admin menu to access all features.
Quick Start
Once installed, the plugin works out of the box. Here's how to get started with the most common features:
Create a Custom Post Type
Create a JSON file at AdpApp/posttypes/product.json:
{
"singular": "Product",
"plural": "Products"
}
Create a Custom Shortcode
Create a Blade template at AdpApp/shortcodes/hello.blade.php:
<h1>Hello, {{ $name ?? 'World' }}!</h1>
Use it anywhere: [hello name="WordPress"]
Create a Server Component
Create a Blade template at AdpApp/servercomponents/my-alert.blade.php:
<div class="alert">{{ $message }}</div>
Use it anywhere: <my-alert message="Hello!"></my-alert>
App Folder Structure
The AdpApp folder should be placed in your active theme directory. Here's the complete structure:
your-theme/
└── AdpApp/
├── admindashwidgets/ # Custom dashboard widgets
│ ├── {name}.blade.php # Widget template
│ └── {name}.json # Widget config
├── annotations/ # (auto-created for annotation storage)
├── cache/ # Blade template cache (auto-created)
├── conditionals/ # Conditional display templates
│ ├── {name}.blade.php # Conditional template
│ └── {name}.json # Conditional config
├── css/ # Dynamic CSS files
│ └── {location}-{context}[-{ids}].css
├── helptabs/ # Custom help tabs
│ ├── {name}.blade.php # Help tab template
│ └── {name}.json # Help tab config
├── js/ # Dynamic JS files
│ └── {location}-{context}[-{ids}].js
├── livecomponents/ # Live (SSE) web components
│ ├── {name}.blade.php # Component template
│ ├── {name}.json # Component config
│ └── {name}-flows/ # Component event flows
├── metaboxes/ # Custom meta boxes
│ └── {name}.json # CMB2 meta box config
├── pages/ # Custom page routing
│ └── {page-name}/
│ └── {param}.blade.php
├── posttypes/ # Custom post types
│ └── {name}.json # Post type config
├── servercomponents/ # Server-side web components
│ ├── {name}.blade.php # Component template
│ ├── {name}.json # Component config
│ ├── {name}-flows/ # Component event flows
│ └── global-states.json # Global state definitions
├── shortcodes/ # Custom shortcodes
│ └── {name}.blade.php # Shortcode template
├── taxonomies/ # Custom taxonomies
│ └── {name}.json # Taxonomy config
├── widgetareas/ # Custom widget areas
│ └── {name}.json # Widget area config
└── widgets/ # Custom widgets
├── {name}.blade.php # Widget template
└── {name}.json # Widget config
Features
Conditionals
Conditionals allow you to show or hide Blade templates based on configurable conditions through an admin UI.
Setup:
- Create a Blade template in
AdpApp/conditionals/(e.g.,hero-banner.blade.php) - Create a matching JSON config file (
hero-banner.json)
Config file format:
{
"Name": "Hero Banner",
"Contents": {
"title": "Default Title",
"description": "Default Description"
}
}
Available conditions (via admin UI):
- Post Type Is — Show/hide based on current post type
- Post ID In — Show/hide on specific post IDs
- Url Is — Show/hide on specific URLs
- Function Is — Call a whitelisted WordPress function
- Taxonomy Is — Show/hide on taxonomy archives
- Terms In — Show/hide on specific taxonomy terms
- Is Mobile / Is Desktop — Device-based display
Usage in templates:
@include('conditionals.hero-banner')
Or via shortcode:
[adpConditionals slug="hero-banner"]

Shortcodes
Place a Blade file in AdpApp/shortcodes/ and it automatically becomes a shortcode with the file name.
Example:
Create AdpApp/shortcodes/greeting.blade.php:
<h2>Hello, {{ $name }}!</h2>
<p>Welcome to {{ $site_name }}.</p>
Usage:
[greeting name="John" site_name="My Site"]
All shortcode attributes are available as variables in the Blade template.
Custom Post Types
Create a JSON file in AdpApp/posttypes/ to register a custom post type.
Minimal config (product.json):
{
"singular": "Product",
"plural": "Products"
}
Full config with extra arguments:
{
"singular": "Product",
"plural": "Products",
"extraArgs": {
"supports": ["title", "editor", "thumbnail", "custom-fields"],
"menu_icon": "dashicons-cart",
"has_archive": true,
"rewrite": { "slug": "products" }
}
}
The filename becomes the post type slug (e.g., product → product post type).
Custom Taxonomies
Create a JSON file in AdpApp/taxonomies/ to register a custom taxonomy.
Config (product-category.json):
{
"posttype": "product",
"singular": "Product Category",
"plural": "Product Categories"
}
With extra arguments:
{
"posttype": "product",
"singular": "Product Tag",
"plural": "Product Tags",
"extraArgs": {
"hierarchical": false,
"rewrite": { "slug": "product-tags" }
}
}
Custom Meta Boxes
The plugin uses CMB2 for meta box registration. Place a JSON config file in AdpApp/metaboxes/.
Config (page-settings.json):
{
"config": {
"id": "page-settings",
"title": "Page Settings",
"object_types": ["page"],
"context": "normal",
"priority": "high"
},
"fields": {
"subtitle": {
"name": "Subtitle",
"type": "text",
"showinadmin": true
},
"hero_image": {
"name": "Hero Image",
"type": "file"
}
}
}
Special field options:
showinadmin: true— Shows the field as a column in the admin post listshowon— Conditionally show the meta box:"showon": { "ids": "1,2,3" }or by template:
"showon": { "templates": "template-about.php,template-contact.php" }
Front-end usage:
[adpMetaForm metaboxid="page-settings" objectid="21"]
Server Components
Server components are reusable HTML web components powered by the Realm.js framework. They render on the server and can be used as HTML tags anywhere in your WordPress site.
Naming convention: Component names must be at least two words separated by dashes (e.g., my-alert, user-card).
Required files:
AdpApp/servercomponents/my-alert.blade.php— The templateAdpApp/servercomponents/my-alert.json— The config
Config (my-alert.json):
{
"attributes": {
"message": {
"type": "string",
"default": "Hello World"
},
"type": {
"type": "string",
"default": "info"
}
},
"states": {
"isVisible": {
"type": "boolean",
"default": true
}
}
}
Template (my-alert.blade.php):
<div class="alert alert-{{ $type }}" x-show="isVisible">
{{ $message }}
</div>
Event flows (optional):
Create a directory AdpApp/servercomponents/my-alert-flows/ with PHP files:
listen-click.php— Handles click eventslisten-mounted.php— Runs when component is mountedtrigger-update.php— Triggers custom events
Usage anywhere:
<my-alert message="Success!" type="success"></my-alert>
Global states (AdpApp/servercomponents/global-states.json):
{
"theme": {
"type": "string",
"default": "light",
"storage": "local"
},
"userLoggedIn": {
"type": "boolean",
"default": false
}
}
Live Components
Same as server components but with real-time updates via Server-Sent Events (SSE). The component automatically re-renders when data changes on the server.
Setup: Same as server components, but place files in AdpApp/livecomponents/.
Important: Live component names must be different from server component names.
Example (live-stock-ticker.blade.php):
<div class="stock-ticker">
<span class="symbol">{{ $symbol }}</span>
<span class="price">{{ $price }}</span>
</div>
The SSE connection is automatically established and updates are pushed to the component without page reloads.
Conditional CSS & JS
Optimize performance by conditionally loading CSS and JS files only where needed.
File naming convention:
{location}-{context}[-{ids}].css
{location}-{context}[-{ids}].js
| Part | Values | Description |
|---|---|---|
location |
header, footer |
Where to load the file |
context |
template, page, single |
When to load it |
ids |
Comma-separated IDs | Specific template/page/post IDs (optional) |
Examples:
| Filename | Loads when |
|---|---|
header-page.css |
On any page |
footer-single.css |
On any single post |
header-template-about.php.css |
On the "About" page template |
footer-page-1,2,3.css |
On pages with IDs 1, 2, or 3 |
header-single-42.js |
On post with ID 42 |
Place files in AdpApp/css/ or AdpApp/js/.
Custom Widgets & Widget Areas
Register a widget area:
Create AdpApp/widgetareas/sidebar-main.json:
{
"id": "sidebar-main",
"name": "Main Sidebar",
"description": "Widgets in this area will appear in the main sidebar.",
"before_widget": "<div class=\"widget %2$s\">",
"after_widget": "</div>",
"before_title": "<h3 class=\"widget-title\">",
"after_title": "</h3>"
}
Embed in your theme:
<?php echo adpEmbedWidgetArea('sidebar-main'); ?>
Register a custom widget:
-
Create
AdpApp/widgets/recent-posts-widget.blade.php:<ul> @foreach($instance['posts'] as $post) <li><a href="{{ get_permalink($post->ID) }}">{{ $post->post_title }}</a></li> @endforeach </ul> -
Create
AdpApp/widgets/recent-posts-widget.json:{ "Config": { "Name": "Recent Posts Widget", "ClassName": "AdpRecentPostsWidget", "before_title": "<h4>", "after_title": "</h4>" }, "Fields": { "title": { "label": "Title", "type": "input-text" }, "count": { "label": "Number of Posts", "type": "input-number" } } }
Admin Dashboard Widgets
Create a Blade template and JSON config in AdpApp/admindashwidgets/:
stats-widget.json:
{
"Title": "Site Statistics"
}
stats-widget.blade.php:
<div class="stats">
<p>Total Posts: <?php echo wp_count_posts()->publish; ?></p>
<p>Total Pages: <?php echo wp_count_posts('page')->publish; ?></p>
</div>
The widget automatically appears on the WordPress dashboard.
Custom Help Tabs
Create a Blade template and JSON config in AdpApp/helptabs/:
getting-started.json:
{
"Title": "Getting Started"
}
getting-started.blade.php:
<h3>Welcome to AdpCore</h3>
<p>This plugin provides many tools to help you build WordPress sites faster.</p>
The help tab appears in the WordPress help menu on all admin screens.
Custom Pages (Page Routing)
Register custom URLs and execute code when they're accessed.
URL pattern:
{site-url}/?{page-name}={parameter}
Setup:
- Create a folder in
AdpApp/pages/with the page name (e.g.,testpage/) - Create a Blade template with the parameter as filename (e.g.,
123.blade.php)
When someone visits yoursite.com/?testpage=123, the code in 123.blade.php executes.
Set page title:
<?php $pageTitle = "My Custom Page"; ?>
<h1>{{ $pageTitle }}</h1>
Annotations
Enable collaborative feedback directly on your website. Logged-in users can annotate any part of a page.
Text annotations:
- Select any text on the page
- An annotation icon appears
- Click to open a comment popup
- Add comments and save
Image annotations:
- Add the
annotateclass to any image:<img class="annotate" src="..."> - Draw a selection on the image with your mouse
- Add comments in the popup
All annotations are stored as custom post types (adpannotations) and can be managed in the WordPress admin.
CDN Libraries
Access the Libraries sub-page under Adp Tools to search for JS/CSS libraries from cdnjs.
Search Similar — Finds libraries matching your keyword
Search Exact — Finds the exact library by name
Features:
- Copy CDN URLs to clipboard
- Save libraries to your personal collection
- Create reusable presets with keywords

Admin Tools
The Adp Tools menu provides a collection of useful developer tools. Each tool can be:
- Open Here — Opens inside WordPress admin via iframe
- Open Separate — Opens in a new browser tab
Tools are filterable by category and loaded from tools/adpTools.json.
Wizards
Wizards provide a visual interface for creating configuration and template files. No need to manually create the AdpApp folder structure — wizards generate everything for you.
Access via Adp Tools → Wizards in the WordPress admin.

Built-in Shortcodes Reference
| Shortcode | Description | Example |
|---|---|---|
[adpPostLoop] |
Loop through posts with WP_Query | [adpPostLoop post_type="product" posts_per_page="5"]...[/adpPostLoop] |
[adpPostField] |
Display a post field | [adpPostField field="post_title"] |
[adpHiddenPostField] |
Hidden input for post field | [adpHiddenPostField field="ID" fieldname="post_id"] |
[adpPostMeta] |
Display post meta | [adpPostMeta field="custom_field"] |
[adpPostThumb] |
Display post thumbnail | [adpPostThumb size="thumbnail" cssclass="thumb"] |
[adpFunctionCall] |
Call a whitelisted function | [adpFunctionCall functionname="adp_my_func"] |
[adpIfIsPost] |
Conditional on POST data | [adpIfIsPost variable="submitted"]...[/adpIfIsPost] |
[adpUpdatePostMeta] |
Update post meta | [adpUpdatePostMeta metakey="field" metaval="frompost"] |
[adpDumpVar] |
Debug variable dump | [adpDumpVar variable="wp_query"] |
[adpConditionals] |
Render conditional | [adpConditionals slug="hero-banner"] |
[adpContentView] |
Content CRUD view | [adpContentView contenttype="post" isajaxed="Yes"] |
Event Hooks System
AdpCore provides 50+ event hooks for extending functionality without modifying core code.
Quick Example
// Validate content before creation
add_filter('content_before_create', function($postData) {
if (strlen($postData['post_title']) < 5) {
$postData['post_title'] .= ' (auto-extended)';
}
return $postData;
});
// Send notification after deletion
add_action('content_after_delete', function($postId) {
wp_mail(get_option('admin_email'), 'Content Deleted', "Post {$postId} was deleted.");
});
// Log all API requests
add_action('api_after_request', function($url, $result, $httpCode) {
error_log("[AdpCore API] {$url} - {$httpCode}");
}, 10, 3);
Available Hook Categories
| Category | Hooks | Description |
|---|---|---|
| Plugin Lifecycle | plugin_loaded, plugin_initialized |
Plugin startup events |
| Content CRUD | content_before_create, content_after_create, content_before_update, content_after_update, content_before_delete, content_after_delete, content_list_query_args, content_list_result, content_meta_before_create, content_meta_before_update |
Content operations |
| Post Types | post_type_before_register, post_type_after_register, post_type_args_{name} |
Post type registration |
| Taxonomies | taxonomy_before_register, taxonomy_after_register, taxonomy_args_{name} |
Taxonomy registration |
| Blocks | block_before_register, block_after_register, block_render_{name} |
Gutenberg blocks |
| API | api_before_request, api_after_request, api_request_error |
External API calls |
| Components | component_before_render, component_after_render, component_import_name, component_global_states, component_list, component_sse_data |
Web components |
| Libraries | library_before_save, library_after_save, library_before_remove, library_after_remove, library_search_results, library_search_error, user_library_list, library_presets_list |
CDN library management |
| Conditionals | conditional_before_render, conditional_after_render, conditional_render_args, conditionals_list |
Conditional display |
| Widgets | widgets_before_register, widgets_after_register, widget_area_*, widget_* |
Widget operations |
| Shortcodes | shortcode_before_execute, shortcode_after_execute, shortcode_{tag}_args, shortcode_{tag}_content, shortcode_{tag}_output |
Shortcode execution |
| Security | security_nonce_failed, security_permission_denied |
Security events |
Using EventManager Directly
use AdpCore\Core\EventManager;
// Register a listener
EventManager::on('my_custom_event', function($data) {
// Handle event
});
// Trigger an action
EventManager::doAction('my_custom_event', $data);
// Trigger and get filtered result
$result = EventManager::trigger('my_filter_event', $data);
// Check if event has listeners
if (EventManager::hasListeners('my_event')) {
// Event has listeners
}
// Get all fired events (debugging)
$firedEvents = EventManager::getFiredEvents();
For the complete hooks reference with all parameters and examples, see docs/hooks.md.
Namespaced Classes
The plugin uses PSR-4 autoloading with the AdpCore\ namespace:
src/
├── Core/
│ ├── Plugin.php # Main plugin singleton
│ ├── AdpBlade.php # Blade template engine extension
│ ├── EventManager.php # Event/hook management
│ ├── Content.php # Content CRUD operations
│ ├── Conditionals.php # Conditional display logic
│ ├── Animations.php # AOS animation management
│ └── Annotations.php # Text & image annotations
├── Api/
│ └── ApiClient.php # External API client
├── Admin/
│ ├── AdminTools.php # Admin pages & menus
│ ├── DashboardWidgets.php # Dashboard widget registration
│ ├── HelpTabs.php # Help tab registration
│ ├── Libraries.php # CDN library management
│ ├── MetaBoxes.php # CMB2 metabox registration
│ ├── Widgets.php # Widget & widget area registration
│ └── Wizards.php # Admin wizards
├── Blocks/
│ ├── Blocks.php # Gutenberg block registration
│ └── PostTypes.php # Post type & taxonomy registration
├── Components/
│ ├── ServerComponents.php # Server-side web components
│ └── LiveComponents.php # Live (SSE) web components
├── Shortcodes/
│ └── Shortcodes.php # All shortcode handlers
└── Helpers/
├── Security.php # Security utilities
└── Utils.php # General utilities
Using Classes Directly
use AdpCore\Helpers\Security;
use AdpCore\Helpers\Utils;
use AdpCore\Api\ApiClient;
use AdpCore\Core\EventManager;
// Safe JSON decode
$data = Security::safeJsonDecode($jsonString);
// Safe redirect (validates referer)
Security::safeRedirect('/dashboard');
// Get sanitized request value
$value = Security::get('my_param', 'default');
// Make API call
$response = ApiClient::get('https://api.example.com/data');
// Render a Blade view
$html = Utils::renderBladeView('my-view', 'widgets', ['name' => 'World']);
Backward Compatibility
All existing code continues to work without changes. The lib/ directory files are thin wrappers that delegate to the new namespaced classes:
// These global functions still work:
adpGetUserRole($userId);
adpSafeJsonDecode($json);
adpSendApiCall($url);
adpConditionals($slug);
adpEmbedWidgetArea('sidebar-main');
Security Features
AdpCore includes enterprise-level security hardening:
| Protection | Implementation |
|---|---|
| SQL Injection | All queries use $wpdb->prepare() |
| XSS | All output escaped with esc_html(), esc_attr(), esc_url() |
| CSRF | Nonce verification on all forms |
| Path Traversal | sanitize_file_name(), realpath() verification, .. removal |
| Privilege Escalation | current_user_can() checks on all operations |
| Open Redirects | HTTP_REFERER domain validation |
| JSON Injection | Safe json_decode() wrapper with error handling |
| Arbitrary Code Execution | Function whitelists for adpFunctionCall and "Function Is" condition |
| Content Security Policy | CSP headers whitelisting trusted CDN sources |
| API Security | URL validation, HTTPS enforcement, timeouts, SSL verification |
Architecture
adpcore/
├── src/ # PSR-4 namespaced classes (22 classes)
├── lib/ # Backward compatibility wrappers
├── vendor/ # Composer dependencies
├── docs/ # Documentation
│ └── hooks.md # Event hooks reference
├── tools/ # Admin tools configuration
├── js/ # Plugin JavaScript files
├── composer.json # Autoloading configuration
├── adpCore.php # Plugin entry point
├── CHANGELOG.md # Version history
└── README.md # This file
Requirements
- WordPress 5.0+
- PHP 7.4+
- Composer (for autoloading)
- cURL extension (for API calls)
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run
composer dump-autoload - Submit a pull request
License
GPL-2.0-or-later — See LICENSE for details.