Skip to content
This repository was archived by the owner on Jun 16, 2025. It is now read-only.

Commit 2fee71b

Browse files
committed
feat: Initial plugin engine implementation
Migrated from https://github.com/trakli/webservice based on trakli/webservice#61 Signed-off-by: nfebe <fenn25.fn@gmail.com>
0 parents  commit 2fee71b

25 files changed

Lines changed: 1671 additions & 0 deletions

.github/workflows/tests.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: true
14+
matrix:
15+
php: [ '8.1', '8.2' ]
16+
laravel: [ '^10.0' ]
17+
dependency-version: [ prefer-stable ]
18+
include:
19+
- laravel: '^10.0'
20+
testbench: '^8.0'
21+
22+
name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
23+
24+
steps:
25+
- name: Checkout code
26+
uses: actions/checkout@v3
27+
28+
- name: Setup PHP
29+
uses: shivammathur/setup-php@v2
30+
with:
31+
php-version: ${{ matrix.php }}
32+
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, xml, ctype, iconv, json, pdo_sqlite, tokenizer
33+
coverage: xdebug
34+
35+
- name: Install Dependencies
36+
run: |
37+
composer require "laravel/framework:${{ matrix.laravel }}" --no-update
38+
composer require --dev "orchestra/testbench:${{ matrix.testbench }}" --no-update
39+
composer update --prefer-dist --no-interaction --no-suggest
40+
41+
- name: Execute tests
42+
run: vendor/bin/phpunit --coverage-clover=coverage.xml
43+
44+
- name: Upload coverage to Codecov
45+
uses: codecov/codecov-action@v3
46+
with:
47+
file: ./coverage.xml
48+
flags: unittests
49+
env_vars: OS,PYTHON
50+
name: codecov-umbrella
51+
fail_ci_if_error: false
52+
verbose: true

.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Dependencies
2+
/vendor/
3+
/node_modules/
4+
5+
# IDE
6+
/.idea/
7+
/.vscode/
8+
9+
# PHPUnit
10+
/coverage/
11+
.phpunit.cache/
12+
.phpunit.result.cache
13+
14+
# Code quality
15+
.php-cs-fixer.cache
16+
.phpcs-cache/
17+
18+
# Logs
19+
*.log

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
## [Unreleased]
6+
7+
### Added
8+
- Initial release of the Trakli Plugin Engine
9+
- Plugin discovery and registration
10+
- Plugin management commands
11+
- Configuration system
12+
- Event system for plugin lifecycle
13+
14+
## [1.0.0] - 2025-06-14
15+
16+
### Added
17+
- First stable release
18+
- Complete plugin management system
19+
- Documentation
20+
- Test suite

README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Trakli Plugin Engine
2+
3+
A flexible and powerful plugin system for Laravel applications.
4+
5+
## Features
6+
7+
- Plugin discovery and registration
8+
- Enable/disable plugins
9+
- Plugin dependencies
10+
- Console commands for plugin management
11+
- Event-driven architecture
12+
- Easy to extend
13+
14+
## Installation
15+
16+
1. Install the package via Composer:
17+
18+
```bash
19+
composer require trakli/plugin-engine
20+
```
21+
22+
2. Publish the configuration file (optional):
23+
24+
```bash
25+
php artisan vendor:publish --provider="Trakli\PluginEngine\Providers\PluginServiceProvider" --tag=config
26+
```
27+
28+
## Configuration
29+
30+
Edit the `config/plugins.php` file to configure the plugin system:
31+
32+
```php
33+
return [
34+
'path' => base_path('plugins'), // Path where plugins are stored
35+
'namespace' => 'Plugins', // Root namespace for plugins
36+
];
37+
```
38+
39+
## Usage
40+
41+
### Available Commands
42+
43+
- `plugin:list` - List all available plugins
44+
- `plugin:info {id}` - Show information about a plugin
45+
- `plugin:enable {id}` - Enable a plugin
46+
- `plugin:disable {id}` - Disable a plugin
47+
- `plugin:install {package}` - Install a plugin
48+
- `plugin:discover` - Discover and register all available plugins
49+
50+
### Creating a Plugin
51+
52+
1. Create a new directory in the `plugins` directory (or your configured path)
53+
2. Create a `plugin.json` file with the following structure:
54+
55+
```json
56+
{
57+
"id": "example-plugin",
58+
"name": "Example Plugin",
59+
"description": "A sample plugin",
60+
"version": "1.0.0",
61+
"namespace": "Plugins\\Example",
62+
"provider": "Plugins\\Example\\ExampleServiceProvider",
63+
"enabled": true,
64+
"requires": {
65+
"php": ">=8.1",
66+
"laravel/framework": "^10.0"
67+
}
68+
}
69+
```
70+
71+
3. Create a service provider for your plugin:
72+
73+
```php
74+
<?php
75+
76+
namespace Plugins\Example;
77+
78+
use Illuminate\Support\ServiceProvider;
79+
80+
class ExampleServiceProvider extends ServiceProvider
81+
{
82+
public function register()
83+
{
84+
// Register bindings
85+
}
86+
87+
public function boot()
88+
{
89+
// Boot logic
90+
$this->loadRoutesFrom(__DIR__.'/routes/web.php');
91+
$this->loadViewsFrom(__DIR__.'/resources/views', 'example');
92+
$this->loadMigrationsFrom(__DIR__.'/database/migrations');
93+
}
94+
}
95+
```
96+
97+
## Plugin Structure
98+
99+
```
100+
plugins/
101+
example-plugin/
102+
src/
103+
Http/
104+
Controllers/
105+
Models/
106+
Providers/
107+
ExampleServiceProvider.php
108+
resources/
109+
views/
110+
routes/
111+
web.php
112+
database/
113+
migrations/
114+
plugin.json
115+
README.md
116+
```
117+
118+
## Events
119+
120+
The plugin system dispatches several events that you can listen for:
121+
122+
- `Trakli\PluginEngine\Events\PluginEnabling` - Fired before a plugin is enabled
123+
- `Trakli\PluginEngine\Events\PluginEnabled` - Fired after a plugin is enabled
124+
- `Trakli\PluginEngine\Events\PluginDisabling` - Fired before a plugin is disabled
125+
- `Trakli\PluginEngine\Events\PluginDisabled` - Fired after a plugin is disabled
126+
- `Trakli\PluginEngine\Events\PluginInstalled` - Fired after a plugin is installed
127+
- `Trakli\PluginEngine\Events\PluginDiscovered` - Fired when a plugin is discovered
128+
129+
## License
130+
131+
This package is proprietary and confidential. All rights reserved.

composer.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "trakli/plugin-engine",
3+
"description": "Plugin system for Trakli applications",
4+
"type": "library",
5+
"license": "proprietary",
6+
"autoload": {
7+
"psr-4": {
8+
"Trakli\\PluginEngine\\": "src/"
9+
}
10+
},
11+
"autoload-dev": {
12+
"psr-4": {
13+
"Trakli\\PluginEngine\\Tests\\": "tests/"
14+
}
15+
},
16+
"authors": [
17+
{
18+
"name": "Trakli Team",
19+
"email": "dev@trakli.com"
20+
}
21+
],
22+
"require": {
23+
"php": "^8.1",
24+
"illuminate/support": "^10.0",
25+
"illuminate/console": "^10.0",
26+
"illuminate/filesystem": "^10.0",
27+
"illuminate/database": "^10.0"
28+
},
29+
"require-dev": {
30+
"orchestra/testbench": "^8.0",
31+
"phpunit/phpunit": "^10.0",
32+
"mockery/mockery": "^1.5"
33+
},
34+
"extra": {
35+
"laravel": {
36+
"providers": [
37+
"Trakli\\PluginEngine\\Providers\\PluginServiceProvider"
38+
]
39+
}
40+
},
41+
"minimum-stability": "dev",
42+
"prefer-stable": true,
43+
"scripts": {
44+
"test": "vendor/bin/phpunit",
45+
"test-coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html coverage"
46+
}
47+
}

config/plugins.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
return [
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Plugin Path
7+
|--------------------------------------------------------------------------
8+
|
9+
| This value is the path where your plugins will be located. By default,
10+
| it's set to the 'plugins' directory in your application's base path.
11+
|
12+
*/
13+
'path' => base_path('plugins'),
14+
15+
/*
16+
|--------------------------------------------------------------------------
17+
| Plugin Namespace
18+
|--------------------------------------------------------------------------
19+
|
20+
| This value is the root namespace for your plugins. Each plugin's service
21+
| provider will be registered under this namespace.
22+
|
23+
*/
24+
'namespace' => 'Plugins',
25+
];

examples/example/README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Trakli Plugin System
2+
3+
## Plugin Structure
4+
5+
Plugins should follow this directory structure:
6+
7+
```
8+
plugins/
9+
├── example/ # Plugin directory (must match plugin ID)
10+
│ ├── src/ # Plugin source code
11+
│ │ ├── Http/ # Controllers, Middleware, etc.
12+
│ │ │ └── Controllers/ # Controller classes
13+
│ │ ├── Models/ # Eloquent models
14+
│ │ └── ExampleServiceProvider.php # Service provider
15+
│ ├── resources/ # Views, assets, translations
16+
│ │ ├── assets/ # Frontend assets (CSS, JS, images)
17+
│ │ └── views/ # Blade templates
18+
│ ├── routes/ # Route files
19+
│ │ └── web.php # Web routes
20+
│ ├── composer.json # Composer dependencies
21+
│ └── plugin.json # Plugin manifest
22+
```
23+
24+
## Plugin Manifest (plugin.json)
25+
26+
Each plugin must have a `plugin.json` file in its root directory with the following structure:
27+
28+
```json
29+
{
30+
"id": "example",
31+
"name": "Example Plugin",
32+
"description": "A brief description of what this plugin does.",
33+
"version": "1.0.0",
34+
"namespace": "Trakli\\ExamplePlugin",
35+
"provider": "Trakli\\ExamplePlugin\\ExampleServiceProvider",
36+
"enabled": true,
37+
"requires": {
38+
"php": ">=8.1",
39+
"laravel/framework": "^10.0"
40+
}
41+
}
42+
```
43+
44+
### Field Descriptions
45+
46+
- **id**: (Required) A unique identifier for your plugin (e.g., `example`). This should match the plugin's directory name exactly and use only lowercase alphanumeric characters and hyphens.
47+
- **name**: (Required) Human-readable name of the plugin.
48+
- **description**: Brief description of what the plugin does.
49+
- **version**: Current version of the plugin (following [SemVer](https://semver.org/)).
50+
- **namespace**: Base PHP namespace for the plugin's classes. Should follow the format: `Trakli\\{PluginName}` where PluginName is in StudlyCase.
51+
- **provider**: Fully qualified class name of the service provider.
52+
- **enabled**: Whether the plugin is enabled by default.
53+
- **requires**: (Optional) PHP and package dependencies.
54+
55+
## Naming Conventions
56+
57+
### Plugin ID
58+
- Use only lowercase alphanumeric characters and hyphens (e.g., `example`, `user-import`)
59+
- Must match the plugin's directory name exactly
60+
- Keep it short but descriptive
61+
- Examples:
62+
- `analytics`
63+
- `payments`
64+
- `user-import`
65+
66+
### Namespace
67+
- Follow PSR-4 autoloading standards
68+
- Use the format: `Trakli\\{PluginName}` where PluginName is in StudlyCase
69+
- Examples:
70+
- ID: `analytics` → Namespace: `Trakli\\Analytics`
71+
- ID: `user-import` → Namespace: `Trakli\\UserImport`
72+
73+
### Directory Structure
74+
- The plugin directory name must exactly match the plugin ID
75+
- Use `kebab-case` for file and directory names
76+
- Follow Laravel's standard directory structure
77+
78+
## Best Practices
79+
80+
1. **Unique IDs**: Always use a unique ID for your plugin to avoid conflicts.
81+
2. **Version Control**: Include your plugin in version control with its dependencies.
82+
3. **Dependencies**: Clearly specify all dependencies in `composer.json`.
83+
4. **Configuration**: Use Laravel's configuration system for plugin settings.
84+
5. **Migrations**: Include database migrations in the `database/migrations` directory.
85+
6. **Assets**: Publish assets using Laravel's asset publishing.
86+
7. **Documentation**: Include a README.md in your plugin's root directory.
87+
88+
## Example Plugin
89+
90+
See the `example` directory for a complete example plugin implementation.

0 commit comments

Comments
 (0)