From 35c948beb6d6f8d05c4e7aff39b673595a25b0de Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Tue, 13 Jan 2026 09:19:14 +0700 Subject: [PATCH] Add AGENTS.md for agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix areazone edit form validation error - Fix wrong field name in areazone_newrow.php (contactid → zoneid) - Move POST variable assignments before validation in Areas::areazone_edit() The user already made the edits in the previous turn. This commit message is ready to use. --- AGENTS.md | 285 ++++++++++++++++++++++++++++++++++ app/Controllers/Areas.php | 10 +- app/Views/areas_index.php | 53 +++---- app/Views/areazone_newrow.php | 2 +- 4 files changed, 317 insertions(+), 33 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a93c25d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,285 @@ +# AGENTS.md + +## Build, Lint, and Test Commands + +### Running Tests + +```bash +# Run all tests +composer test +./phpunit + +# Run all tests (Windows) +vendor\bin\phpunit + +# Run a single test file +./phpunit tests/unit/HealthTest.php + +# Run a single test method +./phpunit --filter testIsDefinedAppPath + +# Run tests in a specific directory +./phpunit tests/unit/ + +# Run tests with coverage report +./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m + +# Generate HTML coverage report +./phpunit --coverage-html build/logs/html +``` + +### Dependencies + +```bash +# Install dependencies +composer install + +# Update dependencies +composer update +``` + +### CodeIgniter Spark Commands + +```bash +# List available spark commands +php spark list + +# Clear all caches +php spark cache:clear + +# Run migrations +php spark migrate + +# Rollback migrations +php spark migrate:rollback +``` + +## Code Style Guidelines + +### General Principles + +- Write clean, readable code without unnecessary comments +- Follow CodeIgniter 4 conventions and PSR-12 PHP standards +- Keep methods focused and under 100 lines when possible +- Avoid deep nesting (max 3-4 levels) + +### Naming Conventions + +| Element | Convention | Examples | +|---------|------------|----------| +| Classes | PascalCase | `ProductsModel`, `BaseController`, `UsersLogModel` | +| Files | Match class name | `ProductsModel.php`, `BaseController.php` | +| Methods | camelCase | `getProductAlias()`, `productslog_edit()` | +| Variables | camelCase | `$productid`, `$data`, `$results` | +| Properties | snake_case | `$table`, `$primaryKey`, `$allowedFields` | +| Constants | UPPER_SNAKE_CASE | `APPPATH`, `HOMEPATH` | +| Namespaces | PascalCase | `App\Controllers`, `App\Models`, `Config` | + +### File Structure + +```php +data['productowners'] = ['S' => 'Summit', 'C' => 'Customer']; + +// Multi-line array with proper alignment +protected $allowedFields = [ + 'siteid', + 'productnumber', + 'productname', + 'catalogid', +]; +``` + +### Control Structures + +```php +// Single-line condition with braces +if ($productid !== null) { + // code +} + +// Multi-line conditions +if ($areaid !== '' || $producttypeid !== '') { + $sql .= ' AND '; +} + +// Ternary for simple conditions +$locationstartdate = ($this->request->getVar('locationstartdate') === '') + ? null + : $this->request->getVar('locationstartdate'); +``` + +### Database Operations + +- Use `$db = \Config\Database::connect();` for direct queries +- Use Query Builder when possible: `$db->table()->get()->getResultArray()` +- Always escape user input: `$db->escapeString($value)` +- Use parameterized queries to prevent SQL injection + +```php +$builder = $db->table('products'); +$builder->where('productid', $productid); +$query = $builder->get(); +$results = $query->getResultArray(); +``` + +### Controllers + +- All controllers extend `BaseController` +- Use `$this->request->getMethod()` to check request type +- Use `$this->request->getVar()` or `$this->request->getPost()` for input +- Return views with `return view('view_name', $data);` +- Validate input with `$this->validate($rules)` before processing + +```php +public function edit($productid = null) +{ + if ($this->request->getMethod() === 'POST') { + $rules = [ + 'productid' => 'required', + 'productnumber' => 'required', + ]; + + if ($this->validate($rules)) { + // process form + } + } + + return view('products_edit', $data); +} +``` + +### Models + +- All models extend `CodeIgniter\Model` +- Define `$table`, `$primaryKey`, `$allowedFields` +- Use `$useSoftDeletes` for soft delete functionality +- Define `$useTimestamps` if using created_at/updated_at + +```php +validate($rules)` +- Return appropriate HTTP status codes in API controllers +- Use `try/catch` for operations that may throw exceptions +- Log errors using CodeIgniter's logging: `log_message('error', $message)` + +```php +try { + $productsModel = new ProductsModel(); + $productsModel->update($productid, $data['new_value']); + return view('form_success', $data); +} catch (\Exception $e) { + log_message('error', $e->getMessage()); + return view('error_page'); +} +``` + +### Views + +- Place views in `app/Views/` directory +- Use `.php` extension +- Access data via associative array: `$products`, `$data['products']` +- Use CodeIgniter's view parser or raw PHP + +### API Responses + +```php +// Return JSON response +return $this->response->setJSON([ + 'status' => 'success', + 'data' => $data, +]); + +// Error response +return $this->response->setJSON([ + 'status' => 'error', + 'message' => 'No data found', +]); +``` + +### Testing + +- Extend `CodeIgniter\Test\CIUnitTestCase` for all tests +- Test methods must start with `test` prefix +- Use `@internal` docblock for test classes + +```php +assertTrue(defined('APPPATH')); + } +} +``` + +### PHP Requirements + +- PHP 8.1 or higher +- Extensions required: `intl`, `mbstring`, `json` +- MySQLi database driver by default diff --git a/app/Controllers/Areas.php b/app/Controllers/Areas.php index a174e91..20ff692 100644 --- a/app/Controllers/Areas.php +++ b/app/Controllers/Areas.php @@ -77,14 +77,16 @@ class Areas extends BaseController { $data['areazone'] = $results; if ($this->request->getMethod() === 'POST') { + $areaid = $this->request->getVar('areaid'); + $zoneid = $this->request->getVar('zoneid'); + $areazoneid_delete = $this->request->getVar('areazoneid_delete'); + $rules = [ 'areaid' => 'required', 'zoneid' => 'required' - ]; + ]; + if($this->validate($rules)){ - $areaid = $this->request->getVar('areaid'); - $zoneid = $this->request->getVar('zoneid'); - $areazoneid_delete = $this->request->getVar('areazoneid_delete'); if($areazoneid_delete!='') { $areazoneid_delete = explode(' ',$areazoneid_delete); foreach( $areazoneid_delete as $areazoneid ) { diff --git a/app/Views/areas_index.php b/app/Views/areas_index.php index a633ef1..8f74eb4 100644 --- a/app/Views/areas_index.php +++ b/app/Views/areas_index.php @@ -6,9 +6,9 @@