MyAdmin plugin that provisions/deprovisions cPanel licenses as VPS addons via the Detain\MyAdminVpsCpanel namespace.
composer install # install deps
vendor/bin/phpunit tests/ -v # run tests
vendor/bin/phpunit --coverage-html build/coverage # coverage report- Entry:
src/Plugin.php— registers hooks viagetHooks()usingSymfony\Component\EventDispatcher\GenericEvent - Addon function:
src/vps_add_cpanel.php— procedural, no namespace, usesAddServiceAddon - Tests:
tests/PluginTest.php·tests/VpsAddCpanelFileTest.php— PHPUnit 9.6,Detain\MyAdminVpsCpanel\Testsnamespace - Autoload: PSR-4
Detain\MyAdminVpsCpanel\→src/· dev tests →tests/ - CI/CD:
.github/contains workflows for automated testing and deployment pipelines - IDE config:
.idea/contains inspectionProfiles, deployment.xml, and encodings.xml for JetBrains IDE settings
public static function getHooks(): array {
return [
'function.requirements' => [__CLASS__, 'getRequirements'],
self::$module.'.load_addons' => [__CLASS__, 'getAddon'],
self::$module.'.settings' => [__CLASS__, 'getSettings'],
];
}$addon = new \AddonHandler();
$addon->setModule(self::$module)
->set_text('CPanel')
->set_text_match('CPanel (.*) Accounts')
->set_cost(VPS_CPANEL_COST)
->set_require_ip(true)
->setEnable([__CLASS__, 'doEnable'])
->setDisable([__CLASS__, 'doDisable'])
->register();
$serviceOrder->addAddon($addon);- Get service info:
$serviceInfo = $serviceOrder->getServiceInfo() - Get settings:
$settings = get_module_settings(self::$module) - Log:
myadmin_log(self::$module, 'info', self::$name.' Activation', __LINE__, __FILE__, self::$module, $serviceInfo[$settings['PREFIX'].'_id']) - Load functions:
function_requirements('get_cpanel_license_data_by_ip') - Check by IP:
get_cpanel_license_data_by_ip($serviceInfo[$settings['PREFIX'].'_ip']) - Activate:
activate_cpanel($ip, 31369)· Deactivate:deactivate_cpanel($ip) - History:
$GLOBALS['tf']->history->add($settings['TABLE'], 'add_cpanel', $id, $ip, $custid) - Cancel email:
(new \MyAdmin\Mail())->adminMail($subject, $email, false, 'admin/vps_cpanel_canceled.tpl')
- Tabs for indentation (see
.scrutinizer.yml) camelCasefor parameters/properties- Docblocks required:
@author,@package MyAdmin,@category VPS,@return voidon functions insrc/vps_add_cpanel.php VPS_CPANEL_COSTconstant (not a variable) used for addon pricingself::$moduleis always'vps'- No PDO — MyAdmin DB helpers only
- Commit messages: lowercase, descriptive
VPS_CPANEL_COST— set via$settings->add_text_setting()ingetSettings()$settings['PREFIX']— used to key into$serviceInfo(e.g._ip,_id,_custid,_hostname)$settings['TABLE']/$settings['TBLNAME']— history/email context
IMPORTANT: Before every git commit, you MUST ensure Caliber syncs agent configs with the latest code changes.
First, check if the pre-commit hook is already installed:
grep -q "caliber" .git/hooks/pre-commit 2>/dev/null && echo "hook-active" || echo "no-hook"- If hook-active: the hook handles sync automatically — just commit normally. Tell the user: "Caliber will sync your agent configs automatically via the pre-commit hook."
- If no-hook: run Caliber manually before committing:
- Tell the user: "Caliber: Syncing agent configs with your latest changes..."
- Run:
caliber refresh && git add CLAUDE.md .claude/ .cursor/ .cursorrules .github/copilot-instructions.md .github/instructions/ AGENTS.md CALIBER_LEARNINGS.md 2>/dev/null - After it completes, briefly tell the user what Caliber updated. Then proceed with the commit.
If caliber is not found, tell the user: "This project uses Caliber for agent config sync. Run /setup-caliber to get set up."
Read CALIBER_LEARNINGS.md for patterns and anti-patterns learned from previous sessions.
These are auto-extracted from real tool usage — treat them as project-specific rules.