Plugin Architecture
Overview#
CloudOnex Business Suite uses a modular plugin architecture that allows developers to extend functionality while maintaining core system stability. This guide covers the architectural principles, component structure, and best practices for plugin development.
Plugin Structure#
Basic Plugin Directory Structure#
apps/
└── your_plugin/
├── manifest.php
├── boot.php
├── app.php
├── install.php
├── uninstall.php
├── models/
│ └── CustomModel.php
├── views/
│ ├── list.tpl
│ ├── add.tpl
│ └── edit.tpl
├── controllers/
│ └── CustomController.php
└── assets/
├── js/
├── css/
└── img/
Core Files Explanation#
1. Manifest File
<?php
// manifest.php
$plugin = [
'name' => 'Your Plugin Name',
'author' => 'Your Name',
'version' => '1.0.0',
'description' => 'Plugin description',
'url' => 'https://your-website.com',
'priority' => 1,
'build' => 1000,
'requires' => [
'core_version' => '3.0.0',
'php_version' => '8.2.0'
]
];
2. Boot File
<?php
// boot.php - Executes when system boots
// Register menus, hooks, and initialization code
// Add admin menu
$admin_submenu = [
[
'name' => 'Add New',
'link' => U.'your_plugin/app/add/'
],
[
'name' => 'List All',
'link' => U.'your_plugin/app/list/'
]
];
add_menu_admin('Plugin Name', U.'your_plugin/app', 'plugin_icon', 'fa fa-plug', 2, $admin_submenu);
// Register hooks
add_hook('admin_dashboard', 1, function() {
// Dashboard widget code
});
3. Installation Handler
<?php
// install.php - Executes during plugin installation
// Create database tables
$table = new Schema('plugin_table');
$table->add('title', 'varchar', 200);
$table->add('description', 'text');
$table->add('created_at', 'datetime');
$table->add('updated_at', 'datetime');
$table->save();
// Add configuration
add_option('plugin_setting_key', 'default_value');
4. Uninstallation Handler
<?php
// uninstall.php - Cleanup when plugin is uninstalled
// Remove tables
$table = new Schema('plugin_table');
$table->drop();
// Remove configuration
delete_option('plugin_setting_key');
Plugin Components#
1. Models#
<?php
// models/CustomModel.php
use Illuminate\Database\Eloquent\Model;
class CustomModel extends Model
{
protected $table = 'plugin_table';
protected $fillable = ['title', 'description'];
// Define relationships
public function relatedModel()
{
return $this->hasMany('RelatedModel');
}
}
2. Views#
{* views/list.tpl *}
{block name="content"}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{$_L['Items']}</h3>
</div>
<div class="panel-body">
<table class="table table-bordered">
<thead>
<tr>
<th>{$_L['Title']}</th>
<th>{$_L['Description']}</th>
<th>{$_L['Actions']}</th>
</tr>
</thead>
<tbody>
{foreach $items as $item}
<tr>
<td>{$item->title}</td>
<td>{$item->description}</td>
<td>
<a href="{$_url}your_plugin/app/edit/{$item->id}"
class="btn btn-primary btn-xs">
{$_L['Edit']}
</a>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
</div>
{/block}
3. Controllers#
<?php
// app.php - Main controller
require 'models/CustomModel.php';
$action = route(2, 'list');
_auth();
$ui->assign('_application_menu', 'your_plugin');
$ui->assign('_title', 'Your Plugin');
switch ($action) {
case 'list':
$items = CustomModel::orderBy('id', 'desc')->get();
view('app_wrapper', [
'_include' => 'list',
'items' => $items
]);
break;
case 'add':
view('app_wrapper', [
'_include' => 'add'
]);
break;
case 'save':
$validator = new Validator;
$validation = $validator->make($_POST, [
'title' => 'required|max:200',
'description' => 'required'
]);
if ($validation->fails()) {
r2(U.'your_plugin/app/add', 'e', $validation->errors()[0]);
}
$item = new CustomModel;
$item->title = _post('title');
$item->description = _post('description');
$item->save();
r2(U.'your_plugin/app/list', 's', 'Item added successfully');
break;
}
Hook System#
Available Hook Points#
// Register hooks in boot.php
add_hook('admin_dashboard', 1, function() {
// Dashboard content
});
add_hook('client_dashboard', 1, function() {
// Client dashboard content
});
add_hook('invoice_created', 1, function($invoice) {
// Handle new invoice
});
add_hook('payment_received', 1, function($payment) {
// Handle payment
});
Custom Hook Points#
// Define hook point
$result = run_hook('custom_hook_name', $data);
// Register handler
add_hook('custom_hook_name', 1, function($data) {
// Process data
return $modified_data;
});
Database Integration#
Schema Management#
// Create table with relationships
$table = new Schema('plugin_items');
$table->add('title', 'varchar', 200);
$table->add('user_id', 'int', 11);
$table->add_foreign_key('user_id', 'sys_users', 'id', 'CASCADE', 'CASCADE');
$table->save();
Query Building#
// Using Query Builder
$items = DB::table('plugin_items')
->where('user_id', $user_id)
->orderBy('created_at', 'desc')
->get();
// Using Eloquent
$items = CustomModel::with('relatedModel')
->where('status', 'active')
->get();
Security Best Practices#
1. Input Validation#
// Validate user input
$validator = new Validator;
$validation = $validator->make($_POST, [
'email' => 'required|email',
'amount' => 'required|numeric|min:0'
]);
if ($validation->fails()) {
r2(U.'your_plugin/app/add', 'e', $validation->errors()[0]);
}
2. Access Control#
// Check permissions
if (!has_access($user->roleid, 'your_plugin', 'edit')) {
r2(U.'dashboard', 'e', 'Access Denied');
}
// Verify CSRF token
if (!verify_csrf_token()) {
r2(U.'dashboard', 'e', 'Invalid Token');
}
3. SQL Injection Prevention#
// Use parameterized queries
$result = DB::select("SELECT * FROM plugin_items WHERE id = ?", [$id]);
// Use Query Builder
$result = DB::table('plugin_items')
->where('id', $id)
->first();
Plugin Settings#
Configuration Management#
// Save settings
add_option('plugin_setting', $value);
// Retrieve settings
$setting = get_option('plugin_setting');
// Update settings
update_option('plugin_setting', $new_value);
// Delete settings
delete_option('plugin_setting');
Asset Management#
Including Resources#
// Add CSS
add_css('apps/your_plugin/assets/css/style.css');
// Add JavaScript
add_js('apps/your_plugin/assets/js/script.js');
// Add inline script
add_js_script('
$(document).ready(function() {
// Your code here
});
');
Internationalization#
Language Support#
// Add language strings
$_L['plugin_string'] = 'Translated Text';
// Use in templates
{$_L['plugin_string']}
// Use in PHP
_L('plugin_string');
Error Handling#
Proper Exception Handling#
try {
// Plugin operation
$result = perform_operation();
if (!$result) {
throw new Exception('Operation failed');
}
} catch (Exception $e) {
_log($e->getMessage());
r2(U.'your_plugin/app/list', 'e', $e->getMessage());
}
Still stuck? Open a support ticket.