crm-summit/AGENTS.md

6.6 KiB

AGENTS.md

Build, Lint, and Test Commands

Running Tests

# 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

# Install dependencies
composer install

# Update dependencies
composer update

CodeIgniter Spark Commands

# 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

namespace App\Controllers;

use App\Models\ProductsModel;
use CodeIgniter\Controller;

class Products extends BaseController
{
    protected array $data;

    public function index()
    {
        // method body
    }
}

Imports and Namespaces

  • Use explicit imports for all external classes
  • Namespace should reflect file location (App\Controllers\*, App\Models\*)
  • Place namespace at top, followed by imports, then class definition
  • Do not use fully qualified class names inline
<?php

namespace App\Controllers;

use App\Models\ProductsModel;
use App\Models\ProductsLogModel;
use CodeIgniter\Controller;

Indentation and Spacing

  • Use tabs for indentation (4 spaces per tab is acceptable)
  • No trailing whitespace
  • One blank line between method definitions
  • Space around operators: $productid = $value;
  • No space between function name and parentheses: func() not func ()

Arrays and Configuration

// Short array syntax for simple arrays
protected array $data;

$this->data['productowners'] = ['S' => 'Summit', 'C' => 'Customer'];

// Multi-line array with proper alignment
protected $allowedFields = [
    'siteid',
    'productnumber',
    'productname',
    'catalogid',
];

Control Structures

// 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
$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
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 namespace App\Models;

use CodeIgniter\Model;

class ProductsModel extends Model
{
    protected $table = 'products';
    protected $primaryKey = 'productid';
    protected $allowedFields = ['siteid', 'productnumber', 'productname'];
}

Error Handling

  • Use CodeIgniter's built-in validation: $this->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)
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

// 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

use CodeIgniter\Test\CIUnitTestCase;

final class HealthTest extends CIUnitTestCase
{
    public function testIsDefinedAppPath(): void
    {
        $this->assertTrue(defined('APPPATH'));
    }
}

PHP Requirements

  • PHP 8.1 or higher
  • Extensions required: intl, mbstring, json
  • MySQLi database driver by default

Agent Preferences

  • Prefer Serena tools (serena_get_symbols_overview, serena_find_symbol, serena_search_for_pattern) for codebase exploration before falling back to Read, Glob, or Grep.
  • Reserve bash for execution tasks (git, composer, php spark, etc.) and use Serena output to avoid unnecessary token use.