mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-05-30 03:07:56 -04:00
Mailchimp Bugfixes
- Update README.md to reflect information about routes - Add registerAllNamespaces() function to correctly load plugin namespaces - center text in modal title - Properly decrypt the api key - Refactor getAllLists to getLists - Naming simplification of strings when mailchimp_ is redundant or unnecessary - Do not attempt to decrypt a plaintext api_key pasted into the form - Register namespaces early on in system init Signed-off-by: objec <objecttothis@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@ use CodeIgniter\HotReloader\HotReloader;
|
||||
use App\Events\Db_log;
|
||||
use App\Events\Load_config;
|
||||
use App\Events\Method;
|
||||
use App\Libraries\Plugins\PluginManager;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
@@ -25,6 +26,10 @@ use App\Events\Method;
|
||||
* Example:
|
||||
* Events::on('create', [$myInstance, 'myMethod']);
|
||||
*/
|
||||
Events::on('pre_system', static function (): void {
|
||||
PluginManager::registerAllNamespaces();
|
||||
});
|
||||
|
||||
Events::on('pre_system', static function (): void {
|
||||
if (ENVIRONMENT !== 'testing') {
|
||||
if (ini_get('zlib.output_compression')) {
|
||||
|
||||
@@ -186,6 +186,29 @@ class PluginManager
|
||||
return $this->configModel->setValue("{$pluginId}_{$key}", $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers PSR-4 namespaces for all plugin directories without touching the DB.
|
||||
* Call this early (pre_system) so CI4's module route discovery can find each
|
||||
* plugin's Config/Routes.php before the router runs.
|
||||
*/
|
||||
public static function registerAllNamespaces(): void
|
||||
{
|
||||
$pluginsPath = APPPATH . 'Plugins';
|
||||
if (!is_dir($pluginsPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$loader = Services::autoloader();
|
||||
foreach (glob($pluginsPath . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR) ?: [] as $dir) {
|
||||
$name = basename($dir);
|
||||
$namespace = "App\\Plugins\\{$name}";
|
||||
if (!in_array($namespace, self::$registeredNamespaces, true)) {
|
||||
$loader->addNamespace($namespace, $dir . DIRECTORY_SEPARATOR);
|
||||
self::$registeredNamespaces[] = $namespace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function resetStatic(): void
|
||||
{
|
||||
self::$discovered = false;
|
||||
|
||||
@@ -16,13 +16,13 @@ class MailchimpController extends Secure_Controller
|
||||
*/
|
||||
public function postCheckMailchimpApiKey(): ResponseInterface
|
||||
{
|
||||
$lists = $this->getAllMailchimpLists($this->request->getPost('mailchimp_api_key'));
|
||||
$lists = $this->getAllMailchimpLists($this->request->getPost('api_key'));
|
||||
$success = count($lists) > 0;
|
||||
|
||||
return $this->response->setJSON([
|
||||
'success' => $success,
|
||||
'message' => lang('MailchimpPlugin.mailchimp_key_' . ($success ? '' : 'un') . 'successfully'),
|
||||
'mailchimp_lists' => $lists
|
||||
'success' => $success,
|
||||
'message' => lang('MailchimpPlugin.key_' . ($success ? '' : 'un') . 'successfully'),
|
||||
'lists' => $lists
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace App\Plugins\MailchimpPlugin\Libraries;
|
||||
|
||||
use CodeIgniter\Encryption\EncrypterInterface;
|
||||
use Config\Services;
|
||||
|
||||
/**
|
||||
* MailChimp API v3 REST client Connector
|
||||
*
|
||||
@@ -13,8 +10,6 @@ use Config\Services;
|
||||
* Inspired by the work of:
|
||||
* - Rajitha Bandara: https://github.com/rajitha-bandara/ci-mailchimp-v3-rest-client
|
||||
* - Stefan Ashwell: https://github.com/stef686/codeigniter-mailchimp-api-v3
|
||||
*
|
||||
* @property encrypterinterface encrypter
|
||||
*/
|
||||
class MailchimpConnector
|
||||
{
|
||||
@@ -23,11 +18,7 @@ class MailchimpConnector
|
||||
|
||||
public function __construct(string $apiKey)
|
||||
{
|
||||
$mailchimpApiKey = !empty($apiKey) ? $apiKey : '';
|
||||
|
||||
if (!empty($mailchimpApiKey)) {
|
||||
$this->apiKey = Services::encrypter()->decrypt($mailchimpApiKey);
|
||||
}
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
if (!empty($this->apiKey)) {
|
||||
// Replace <dc> with correct datacenter obtained from the last part of the api key
|
||||
|
||||
@@ -37,7 +37,7 @@ class MailchimpLibrary
|
||||
* @return array|bool
|
||||
* @see http://developer.mailchimp.com/documentation/mailchimp/reference/lists/#read-get_lists
|
||||
*/
|
||||
public function getAllLists(array $parameters = ['fields' => 'lists.id,lists.name,lists.stats.member_count,lists.stats.merge_field_count']): bool|array
|
||||
public function getLists(array $parameters = ['fields' => 'lists.id,lists.name,lists.stats.member_count,lists.stats.merge_field_count']): bool|array
|
||||
{
|
||||
return $this->connector->call('/lists', 'GET', $parameters);
|
||||
}
|
||||
@@ -229,14 +229,11 @@ class MailchimpLibrary
|
||||
public function synchronizeSubscription(array $customerData): bool
|
||||
{
|
||||
try {
|
||||
if (!$this->subscribeCustomer($customerData)) {
|
||||
throw new Exception("Customer ID {$customerData['person_id']}");
|
||||
}
|
||||
return $this->subscribeCustomer($customerData);
|
||||
} catch (Exception $e) {
|
||||
log_message('error', "Failed to sync customer to Mailchimp: {$e->getMessage()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function subscribeCustomer(array $customerData): bool
|
||||
@@ -284,7 +281,7 @@ class MailchimpLibrary
|
||||
$mailchimpInfo = $this->getMemberInfo($listId, $customerData->email);
|
||||
|
||||
if ($mailchimpInfo !== false) {
|
||||
$mailchimpData['mailchimp_info'] = $mailchimpInfo;
|
||||
$mailchimpData['mailchimpActivity'] = $mailchimpInfo;
|
||||
|
||||
$mailchimpData['subscriptionStatusOptions'] = $this->getSubscriptionStatusOptionViewData();
|
||||
|
||||
@@ -315,11 +312,11 @@ class MailchimpLibrary
|
||||
++$total;
|
||||
}
|
||||
|
||||
$mailchimpData['mailchimp_activity']['total'] = $total;
|
||||
$mailchimpData['mailchimp_activity']['open'] = $open;
|
||||
$mailchimpData['mailchimp_activity']['unopen'] = $unopen;
|
||||
$mailchimpData['mailchimp_activity']['click'] = $click;
|
||||
$mailchimpData['mailchimp_activity']['last_open'] = $lastOpen;
|
||||
$mailchimpData['mailchimpActivity']['total'] = $total;
|
||||
$mailchimpData['mailchimpActivity']['open'] = $open;
|
||||
$mailchimpData['mailchimpActivity']['unopen'] = $unopen;
|
||||
$mailchimpData['mailchimpActivity']['click'] = $click;
|
||||
$mailchimpData['mailchimpActivity']['last_open'] = $lastOpen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Plugins\MailchimpPlugin;
|
||||
use App\Libraries\Plugins\BasePlugin;
|
||||
use App\Plugins\MailchimpPlugin\Libraries\MailchimpLibrary;
|
||||
use CodeIgniter\Events\Events;
|
||||
use Config\Services;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
@@ -77,11 +78,23 @@ class MailchimpPlugin extends BasePlugin
|
||||
|
||||
public function getSettings(): array
|
||||
{
|
||||
$encryptedKey = $this->getSetting('api_key', '');
|
||||
$apiKey = '';
|
||||
|
||||
if (!empty($encryptedKey)) {
|
||||
try {
|
||||
$apiKey = Services::encrypter()->decrypt($encryptedKey);
|
||||
} catch (\Exception $e) {
|
||||
// Key stored as plaintext (pre-encryption migration) — use as-is
|
||||
$apiKey = $encryptedKey;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'api_key' => $this->getSetting('api_key', ''),
|
||||
'list_id' => $this->getSetting('list_id', ''),
|
||||
'api_key' => $apiKey,
|
||||
'list_id' => $this->getSetting('list_id', ''),
|
||||
'sync_on_save' => $this->getSetting('sync_on_save', '1'),
|
||||
'enabled' => $this->getSetting('enabled', '0'),
|
||||
'enabled' => $this->getSetting('enabled', '0'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -90,7 +103,10 @@ class MailchimpPlugin extends BasePlugin
|
||||
$normalized = [];
|
||||
|
||||
if (array_key_exists('api_key', $settings)) {
|
||||
$normalized['api_key'] = (string)$settings['api_key'];
|
||||
$rawKey = (string)$settings['api_key'];
|
||||
$normalized['api_key'] = !empty($rawKey)
|
||||
? Services::encrypter()->encrypt($rawKey)
|
||||
: '';
|
||||
}
|
||||
|
||||
if (array_key_exists('list_id', $settings)) {
|
||||
@@ -126,7 +142,7 @@ class MailchimpPlugin extends BasePlugin
|
||||
{
|
||||
log_message('debug', "Customer_deleted event received for ID: {$customer->person_id}");
|
||||
|
||||
$this->mailchimpLibrary->deleteSubscription();
|
||||
$this->mailchimpLibrary->deleteSubscription($customer);
|
||||
}
|
||||
|
||||
private function shouldSyncOnSave(): bool
|
||||
@@ -140,7 +156,7 @@ class MailchimpPlugin extends BasePlugin
|
||||
$apiKey = $this->getSetting('api_key');
|
||||
|
||||
if (empty($apiKey)) {
|
||||
return ['success' => false, 'message' => lang('mailchimp_api_key_required')];
|
||||
return ['success' => false, 'message' => lang('api_key_required')];
|
||||
}
|
||||
|
||||
$result = $this->mailchimpLibrary->getLists();
|
||||
@@ -148,12 +164,12 @@ class MailchimpPlugin extends BasePlugin
|
||||
if ($result && isset($result['lists'])) {
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => lang('mailchimp_key_successfully'),
|
||||
'message' => lang('key_successfully'),
|
||||
'lists' => $result['lists']
|
||||
];
|
||||
}
|
||||
|
||||
return ['success' => false, 'message' => lang('mailchimp_key_unsuccessfully')];
|
||||
return ['success' => false, 'message' => lang('key_unsuccessfully')];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,24 +5,24 @@
|
||||
*/
|
||||
?>
|
||||
|
||||
<?= form_open('MailchimpPlugin/saveMailchimp/', ['id' => 'mailchimp_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
|
||||
<?= form_open(site_url('plugins/saveConfig/mailchimp'), ['id' => 'config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
|
||||
<div id="config_wrapper">
|
||||
<fieldset id="config_info">
|
||||
|
||||
<div id="required_fields_message"><?= lang('MailchimpPlugin.fields_required_message') ?></div>
|
||||
<div id="plugins_header"><?= lang('MailchimpPlugin.configuration') ?></div>
|
||||
<ul id="mailchimp_error_message_box" class="error_message_box"></ul>
|
||||
<ul id="error_message_box" class="error_message_box"></ul>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.api_key'), 'mailchimp_api_key', ['class' => 'control-label col-xs-2']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.api_key'), 'api_key', ['class' => 'control-label col-xs-2']) ?>
|
||||
<div class="col-xs-4">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon input-sm">
|
||||
<span class="glyphicon glyphicon-cloud"></span>
|
||||
</span>
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_api_key',
|
||||
'id' => 'mailchimp_api_key',
|
||||
'name' => 'api_key',
|
||||
'id' => 'api_key',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => esc($settings['api_key'] ?? '')
|
||||
]) ?>
|
||||
@@ -38,17 +38,17 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.lists'), 'mailchimp_list_id', ['class' => 'control-label col-xs-2']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.lists'), 'list_id', ['class' => 'control-label col-xs-2']) ?>
|
||||
<div class="col-xs-4">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon input-sm">
|
||||
<span class="glyphicon glyphicon-user"></span>
|
||||
</span>
|
||||
<?= form_dropdown(
|
||||
'mailchimp_list_id',
|
||||
'list_id',
|
||||
esc($settings['lists'] ?? ''),
|
||||
esc($settings['list_id'] ?? ''),
|
||||
'id="mailchimp_list_id" class="form-control input-sm"'
|
||||
'id="list_id" class="form-control input-sm"'
|
||||
) ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,9 +68,9 @@
|
||||
<script type="text/javascript">
|
||||
// Validation and submit handling
|
||||
$(document).ready(function() {
|
||||
$('#mailchimp_api_key').change(function() {
|
||||
$.post("<?= "checkMailchimpApiKey" ?>", {
|
||||
'mailchimp_api_key': $('#mailchimp_api_key').val()
|
||||
$('#api_key').change(function() {
|
||||
$.post("<?= site_url('plugins/mailchimp/checkApiKey') ?>", {
|
||||
'api_key': $('#api_key').val()
|
||||
},
|
||||
function(response) {
|
||||
$.notify({
|
||||
@@ -78,17 +78,17 @@
|
||||
}, {
|
||||
type: response.success ? 'success' : 'danger'
|
||||
});
|
||||
$('#mailchimp_list_id').empty();
|
||||
$.each(response.mailchimp_lists, function(val, text) {
|
||||
$('#mailchimp_list_id').append(new Option(text, val));
|
||||
$('#list_id').empty();
|
||||
$.each(response.lists, function(val, text) {
|
||||
$('#list_id').append(new Option(text, val));
|
||||
});
|
||||
$('#mailchimp_list_id').prop('selectedIndex', 0);
|
||||
$('#list_id').prop('selectedIndex', 0);
|
||||
},
|
||||
'json'
|
||||
);
|
||||
});
|
||||
|
||||
$('#mailchimp_config_form').validate($.extend(form_support.handler, {
|
||||
$('#config_form').validate($.extend(form_support.handler, {
|
||||
submitHandler: function(form) {
|
||||
$(form).ajaxSubmit({
|
||||
success: function(response) {
|
||||
@@ -102,7 +102,7 @@
|
||||
});
|
||||
},
|
||||
|
||||
errorLabelContainer: '#mailchimp_error_message_box'
|
||||
errorLabelContainer: '#error_message_box'
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -8,32 +8,32 @@
|
||||
?>
|
||||
|
||||
|
||||
<div class="tab-pane" id="customer_mailchimp_info">
|
||||
<div class="tab-pane" id="activity_info">
|
||||
<fieldset>
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.status'), 'mailchimp_status', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.status'), 'status', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_dropdown(
|
||||
'mailchimp_status',
|
||||
'status',
|
||||
$subscriptionStatusOptions,
|
||||
$mailchimpData['status'],
|
||||
['id' => 'mailchimp_status', 'class' => 'form-control input-sm']
|
||||
['id' => 'status', 'class' => 'form-control input-sm']
|
||||
) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.vip'), 'mailchimp_vip', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.vip'), 'vip', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-1">
|
||||
<?= form_checkbox('mailchimp_vip', 1, $mailchimpData['vip'] == 1) ?>
|
||||
<?= form_checkbox('vip', 1, $mailchimpData['vip'] == 1) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.member_rating'), 'mailchimp_member_rating', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.member_rating'), 'member_rating', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_member_rating',
|
||||
'name' => 'member_rating',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpData['member_rating'],
|
||||
'disabled' => ''
|
||||
@@ -42,10 +42,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.activity_total'), 'mailchimp_activity_total', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.activity_total'), 'activity_total', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_activity_total',
|
||||
'name' => 'activity_total',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpActivity['total'],
|
||||
'disabled' => ''
|
||||
@@ -54,10 +54,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.activity_last_open'), 'mailchimp_activity_last_open', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.activity_last_open'), 'activity_last_open', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_activity_last_open',
|
||||
'name' => 'activity_last_open',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpActivity['last_open'],
|
||||
'disabled' => ''
|
||||
@@ -66,10 +66,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.activity_open'), 'mailchimp_activity_open', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.activity_open'), 'activity_open', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_activity_open',
|
||||
'name' => 'activity_open',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpActivity['open'],
|
||||
'disabled' => ''
|
||||
@@ -78,10 +78,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.activity_click'), 'mailchimp_activity_click', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.activity_click'), 'activity_click', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_activity_click',
|
||||
'name' => 'activity_click',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpActivity['click'],
|
||||
'disabled' => ''
|
||||
@@ -90,10 +90,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.activity_unopen'), 'mailchimp_activity_unopen', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.activity_unopen'), 'activity_unopen', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_activity_unopen',
|
||||
'name' => 'activity_unopen',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpActivity['unopen'],
|
||||
'disabled' => ''
|
||||
@@ -102,10 +102,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group form-group-sm">
|
||||
<?= form_label(lang('MailchimpPlugin.email_client'), 'mailchimp_email_client', ['class' => 'control-label col-xs-3']) ?>
|
||||
<?= form_label(lang('MailchimpPlugin.email_client'), 'email_client', ['class' => 'control-label col-xs-3']) ?>
|
||||
<div class="col-xs-4">
|
||||
<?= form_input([
|
||||
'name' => 'mailchimp_email_client',
|
||||
'name' => 'email_client',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => $mailchimpData['email_client'],
|
||||
'disabled' => ''
|
||||
|
||||
@@ -190,6 +190,8 @@ For plugins that only need to listen to events without complex UI or database ta
|
||||
```text
|
||||
app/Plugins/
|
||||
└── ExamplePlugin/ # Plugin directory (self-contained)
|
||||
├── Config/ # Plugin-specific routing (optional)
|
||||
│ └── Routes.php
|
||||
├── Language/ # Plugin-specific translations (self-contained)
|
||||
│ ├── en/
|
||||
│ │ └── ExamplePlugin.php
|
||||
@@ -267,6 +269,8 @@ For plugins that need database tables, controllers, models, and views:
|
||||
```text
|
||||
app/Plugins/
|
||||
└── ExamplePlugin/ # Plugin directory
|
||||
├── Config/ # Plugin-specific routing
|
||||
│ └── Routes.php
|
||||
├── Controllers/ # Plugin controllers
|
||||
│ └── ExampleController.php
|
||||
├── Language/ # Plugin translations (self-contained)
|
||||
@@ -369,6 +373,39 @@ class ExamplePlugin extends BasePlugin
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin Routes
|
||||
|
||||
Plugins can define their own routes in a `Config/Routes.php` file. Routes are *NOT* auto-loaded by the framework when the plugin directory is discovered.
|
||||
|
||||
### Defining Plugin Routes
|
||||
|
||||
Create `app/Plugins/ExamplePlugin/Config/Routes.php`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use CodeIgniter\Router\RouteCollection;
|
||||
|
||||
/**
|
||||
* @var RouteCollection $routes
|
||||
*/
|
||||
$routes->post('plugins/example/action', '\App\Plugins\ExamplePlugin\Controllers\ExampleController::postAction');
|
||||
$routes->get('plugins/example/dashboard', '\App\Plugins\ExamplePlugin\Controllers\ExampleController::getDashboard');
|
||||
```
|
||||
|
||||
### Route Naming Convention
|
||||
|
||||
Use a consistent naming scheme for plugin routes:
|
||||
- Prefix routes with `plugins/` followed by plugin identifier
|
||||
- Examples: `plugins/mailchimp/checkApiKey`, `plugins/example/sync`
|
||||
|
||||
### Full Qualified Class Names
|
||||
|
||||
Always use fully qualified controller names:
|
||||
- `\App\Plugins\ExamplePlugin\Controllers\ExampleController::methodName`
|
||||
|
||||
This ensures routes work correctly regardless of autoloader state.
|
||||
|
||||
## Internationalization (Language Files)
|
||||
|
||||
Plugins can include their own language files, making them completely self-contained. This allows plugins to provide translations without modifying core language files.
|
||||
@@ -442,6 +479,7 @@ Settings are prefixed with the plugin ID (e.g., `example_api_key`) and stored in
|
||||
|---------------------------------------------------------------|-----------------------------------------------------------|
|
||||
| `app/Plugins/ExamplePlugin.php` | `App\Plugins` |
|
||||
| `app/Plugins/ExamplePlugin/ExamplePlugin.php` | `App\Plugins\ExamplePlugin\ExamplePlugin` |
|
||||
| `app/Plugins/ExamplePlugin/Config/Routes.php` | *(Route file - no namespace)* |
|
||||
| `app/Plugins/ExamplePlugin/Models/ExampleModel.php` | `App\Plugins\ExamplePlugin\Models\ExampleModel` |
|
||||
| `app/Plugins/ExamplePlugin/Controllers/ExampleController.php` | `App\Plugins\ExamplePlugin\Controllers\ExampleController` |
|
||||
| `app/Plugins/ExamplePlugin/Libraries/ApiClient.php` | `App\Plugins\ExamplePlugin\Libraries\ApiClient` |
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title"><?= lang('Plugins.plugins') ?></h4>
|
||||
<h4 class="modal-title text-center"><?= lang('Plugins.plugins') ?></h4>
|
||||
</div>
|
||||
<div class="modal-body" id="plugin-config-content"></div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user