2026-04-27 01:47:10 +00:00
|
|
|
# AGENTS.md (English Version)
|
|
|
|
|
|
|
|
|
|
## 🎯 Objective
|
2026-05-21 20:04:41 +00:00
|
|
|
|
|
|
|
|
This project contains the full sources of the Dolibarr ERP and CRM application.
|
|
|
|
|
Every modification must respect:
|
2026-04-27 01:47:10 +00:00
|
|
|
- Dolibarr's modular architecture
|
|
|
|
|
- Compatibility with upstream updates
|
|
|
|
|
- Modern PHP best practices
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ⚠️ Critical Rules (DO NOT VIOLATE)
|
|
|
|
|
|
|
|
|
|
- ❌ Do not break compatibility of PHP functions and methods
|
|
|
|
|
- ❌ Do not introduce external dependencies without validation
|
|
|
|
|
- ❌ Separate page actions in the `/* Actions */` section of the PHP code and the rendering part in the `/* Views */` section
|
2026-07-15 18:40:45 +00:00
|
|
|
- ❌ Never commit directly to `develop` or version branch matching regex `^\d+\.\d+$`
|
2026-05-17 21:57:26 +00:00
|
|
|
- ❌ Never use PHP native curl functions to call a GET or POST URL, but use instead the Dolibarr function getURLContent()
|
2026-04-27 01:47:10 +00:00
|
|
|
- ✅ Use Dolibarr hooks whenever possible
|
|
|
|
|
- ✅ Respect existing naming conventions
|
2026-05-21 20:04:41 +00:00
|
|
|
- ✅ All database table names must use the `llx_` prefix
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 📁 Expected Architecture
|
|
|
|
|
|
|
|
|
|
Module structure:
|
|
|
|
|
`htdocs/mymodule`
|
|
|
|
|
├── `core/`
|
|
|
|
|
├── `class/`
|
|
|
|
|
├── `lib/`
|
|
|
|
|
├── `sql/`
|
|
|
|
|
├── `tpl/`
|
|
|
|
|
└── `admin/`
|
|
|
|
|
|
|
|
|
|
A template of a module directory content can be found in the `htdocs/modulebuilder/template` folder of this project.
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 🔍 Before Coding
|
|
|
|
|
|
|
|
|
|
Before writing any code, the agent **must**:
|
|
|
|
|
- Search for existing similar functions in `htdocs/core/lib/` and `htdocs/core/class/`
|
|
|
|
|
- Check if the concerned object class extends `CommonObject` and use its built-in methods (fetch, create, update, delete, etc.)
|
|
|
|
|
- Review the module's `modMyModule.class.php` for declared permissions and constants
|
|
|
|
|
- Run a search to ensure no equivalent function already exists in the codebase
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-04-27 01:47:10 +00:00
|
|
|
## 🧠 PHP Best Practices
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- PHP >= 7.3 (minimum support); PHP 8.1+ recommended for new external modules
|
|
|
|
|
- ⚠️ When writing a **bug fix**, always target the lowest compatible PHP version
|
|
|
|
|
of the branch being patched — do not use PHP 8.x syntax on a fix targeting v19 or v20
|
|
|
|
|
- Respect PSR-12, but **indentations must use Tabs, not Spaces**
|
|
|
|
|
- Write short, readable, and testable functions
|
2026-04-27 01:47:10 +00:00
|
|
|
- Avoid side effects
|
2026-05-21 20:04:41 +00:00
|
|
|
- Prefer typed properties and return types when PHP version allows
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🗄️ Database
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- Use Dolibarr database functions exclusively — never use PDO or MySQLi directly
|
|
|
|
|
- In pages: use global `$db`
|
|
|
|
|
- In classes: use `$this->db`
|
2026-07-13 10:04:47 +00:00
|
|
|
- ✅ SQL forged by PHP must escaped fields with `db->escape()`, `db->sanitize()`, or by casting values to `(int)` or `(float)`
|
2026-05-21 20:04:41 +00:00
|
|
|
- ✅ Always use `$db->query()` followed by `$db->fetch_object()` or `$db->fetch_array()` to retrieve results
|
|
|
|
|
- ✅ SQL scripts for table and index creation must be placed in `htdocs/install/mysql/tables/` (see existing files for examples)
|
|
|
|
|
- ❌ Never run SQL queries inside loops (avoid N+1 problem — use JOINs or batch queries instead)
|
|
|
|
|
- ✅ Always use `LIMIT` on list queries for performance
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🔌 Hooks & Extensions
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- Prioritize hooks over direct code overrides
|
|
|
|
|
- Before creating a new hook, verify it does not already exist:
|
|
|
|
|
```
|
|
|
|
|
grep -r "executeHooks" htdocs/ | grep 'hookName'
|
|
|
|
|
```
|
|
|
|
|
- Call hooks using the standard pattern:
|
|
|
|
|
```php
|
|
|
|
|
$hookmanager->executeHooks('actionName', $parameters, $object, $action);
|
|
|
|
|
```
|
|
|
|
|
- Name hooks clearly and descriptively (e.g., `formObjectOptions`, `addMoreActionsButtons`)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 🌍 Internationalisation
|
|
|
|
|
|
|
|
|
|
- Never hardcode user-facing strings — always use `$langs->trans('Key')`
|
|
|
|
|
- Language files must be placed in `mymodule/langs/en_US/` (and other locales as needed)
|
2026-07-06 21:55:37 +00:00
|
|
|
- All code comments and variables or functions names must be in English.
|
|
|
|
|
- Language key names must use PascalCase (e.g., `MyModuleLabel`, not `monLibelléModule`)
|
2026-05-21 20:04:41 +00:00
|
|
|
- Load the language file at the top of the page: `$langs->load('mymodule@mymodule')`
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🧪 Testing & Validation
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
Before any modification, verify:
|
|
|
|
|
- Creation / edition / deletion workflows
|
2026-07-06 21:55:37 +00:00
|
|
|
- User rights enforcement (`$user->hasRights("module", "permission")` or `$user->hasRights("module", "objectname", "permission")`)
|
|
|
|
|
- Multi-entity compatibility (add ` AND entity IN ('.getDolEntity("tablename").')`)
|
2026-05-21 20:04:41 +00:00
|
|
|
|
|
|
|
|
If possible:
|
2026-07-06 21:55:37 +00:00
|
|
|
- If doing an external module, add a PHPUnit test file in `yourmoduledir/test/phpunit/`
|
|
|
|
|
- If modifying the Dolibarr code project, add a PHPUnit test file into `test/phpunit/` and add the entry into file `test/phpunit/AllTests.php`.
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🖥️ UI / UX
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- Respect Dolibarr UI — no unsolicited redesigns
|
|
|
|
|
- Reuse existing components (buttons, forms, tables) from `htdocs/core/tpl/`
|
2026-04-27 01:47:10 +00:00
|
|
|
- ❌ No overly complex inline JS
|
2026-05-21 20:04:41 +00:00
|
|
|
- ✅ Place JavaScript in separate files under `mymodule/js/`
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🔒 Security
|
|
|
|
|
|
2026-07-06 21:55:37 +00:00
|
|
|
- Always validate user inputs (`GET`, `POST`) via `GETPOST()` with a type parameter
|
|
|
|
|
- Prevent SQL injection (use `db->escape()` or cast into `(int)` or `(float)`)
|
2026-07-13 10:04:47 +00:00
|
|
|
- Prevent XSS injection by escaping HTML output (use `dolPrintHTML()`, `dolPrintHTMLForAttribute()`)
|
2026-05-21 20:04:41 +00:00
|
|
|
- Always include Dolibarr CSRF tokens in POST forms: `<input type="hidden" name="token" value="'.newToken().'">`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ⚡ Performance
|
|
|
|
|
|
|
|
|
|
- Avoid SQL queries inside loops (N+1 problem)
|
|
|
|
|
- Use JOINs or batch queries instead of multiple sequential queries
|
|
|
|
|
- Apply `LIMIT` and proper indexes on list queries
|
|
|
|
|
- Cache repeated calls to `getDolGlobalString()` or `$conf->global->` in local variables
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🧾 Logs & Debug
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- Use `dol_syslog()` for all logging (with appropriate log level: `LOG_DEBUG`, `LOG_WARNING`, `LOG_ERR`)
|
|
|
|
|
- Do not leave `var_dump()`, `print_r()`, or `die()` in committed code
|
|
|
|
|
- Use Dolibarr's `setEventMessages()` to display user-facing messages
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 🚀 Git Workflow
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- Branch strategy:
|
|
|
|
|
- One branch per major version (bug fixes only)
|
|
|
|
|
- `develop` branch for both fixes and new features
|
|
|
|
|
- ❌ Never commit directly to `main` or `develop` without a reviewed PR
|
|
|
|
|
- Commit message format: `TYPE: #issueNumber Short description`
|
2026-07-06 21:58:07 +00:00
|
|
|
- Types: `NEW`, `FIX` or `CLOSE`
|
2026-05-21 20:04:41 +00:00
|
|
|
- Example: `FIX: #1234 Correct VAT calculation on credit notes`
|
|
|
|
|
- Update the `ChangeLog` file with a summary of significant changes
|
|
|
|
|
- When fixing a bug, apply the patch on the **oldest affected branch first**,
|
|
|
|
|
then cherry-pick forward to newer branches and `develop`
|
|
|
|
|
- Do not introduce new syntax or features unavailable in the branch's minimum PHP version
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
## 🧩 What the Agent MUST Do
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
- Read this file before any modification
|
2026-05-21 20:04:41 +00:00
|
|
|
- Check if an equivalent function already exists before writing new code
|
2026-04-27 01:47:10 +00:00
|
|
|
- Minimize the impact of changes
|
2026-05-21 20:04:41 +00:00
|
|
|
- Propose modular modifications that do not affect unrelated features
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
## ❗ What the Agent MUST NOT Do
|
2026-04-27 01:47:10 +00:00
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
- Perform massive refactoring without an explicit request
|
|
|
|
|
- Change the global architecture of existing modules
|
|
|
|
|
- Delete code without justification and a comment explaining why
|
|
|
|
|
- Add external dependencies (Composer packages, JS libraries) without prior validation
|
2026-07-13 09:48:42 +00:00
|
|
|
- Modify the `ChangeLog` file (this file will be updated by the maintainer during the release process)
|
2026-05-21 20:04:41 +00:00
|
|
|
|
|
|
|
|
---
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
## 💡 Key Principle
|
|
|
|
|
|
|
|
|
|
👉 Always prioritize:
|
|
|
|
|
**extension > modification**
|
|
|
|
|
|
2026-05-21 20:04:41 +00:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 📌 In Case of Doubt
|
2026-04-27 01:47:10 +00:00
|
|
|
|
|
|
|
|
- Keep it simple
|
|
|
|
|
- Be conservative
|
2026-05-21 20:04:41 +00:00
|
|
|
- Ask for confirmation before any critical or irreversible change
|