Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .ai/conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Neuron Framework - Coding Conventions

## Code Style
- Tab indentation (not spaces)
- Opening braces on same line for class declarations, new line for methods/control structures
- Spaces before parentheses in function calls: `function_name ($arg)`
- Spaces around operators and after commas
- PHP closing tag `?>` used in source files
- PSR-4 autoloading under `Neuron\` namespace mapped to `src/Neuron/`

## Input Validation Pattern
All user input goes through `Tools::checkInput()` for validation, then `Tools::getInput()` for retrieval:
1. `checkInput($value, $type)` returns bool - validates format
2. `getInput($data, $key, $type, $default)` returns validated+processed value or default

Supported types: text, varchar, string, html, name, email, username, password, date, datetime, number, int, md5, base64, url, bool, raw

## Database Queries
- Use `Query` class for parameterized queries
- Parameter types: `PARAM_STR`, `PARAM_NUMBER`, `PARAM_DATE`, `PARAM_POINT`
- Supports named parameters (`:name`) and positional (`?`) placeholders

## Testing
- Tests extend `PHPUnit\Framework\TestCase`
- Test namespace: `Neuron\Tests`
- Database-dependent tests use `#[Group('database')]` attribute
- Run: `vendor/bin/phpunit --exclude-group=database`

## Collections
- Base `Collection` class is observable (extends `Observable`)
- Triggers events: 'add', 'set', 'unset'
- Implements Iterator, ArrayAccess, Countable interfaces
44 changes: 44 additions & 0 deletions .ai/project-summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Neuron Framework - Project Summary

## Overview
Neuron is a lightweight PHP framework by CatLab Interactive. It provides core utilities for web applications including input validation, database query building, collections, encryption, URL building, filtering, and localization.

## Architecture

### Core Components
- **Application** (`src/Neuron/Application.php`) - Main application dispatcher, singleton pattern
- **Config** (`src/Neuron/Config.php`) - Configuration loader with dot-notation access and environment overrides
- **Router** (`src/Neuron/Router.php`) - URL routing
- **URLBuilder** (`src/Neuron/URLBuilder.php`) - Static URL construction utilities

### Input Handling
- **Tools** (`src/Neuron/Core/Tools.php`) - Input validation (`checkInput`) and retrieval (`getInput`) for types: text, varchar, string, html, name, email, username, password, date, datetime, number, int, md5, base64, url, bool, raw

### Database
- **Query** (`src/Neuron/DB/Query.php`) - Parameterized SQL query builder with INSERT, UPDATE, DELETE, SELECT support
- **Database** (`src/Neuron/DB/Database.php`) - Database interface
- **MySQL** (`src/Neuron/DB/MySQL.php`) - MySQL implementation

### Collections
- **Collection** (`src/Neuron/Collections/Collection.php`) - Observable collection implementing Iterator, ArrayAccess, Countable
- **ModelCollection** (`src/Neuron/Collections/ModelCollection.php`) - Model-specific collection with ID indexing
- **ErrorCollection** (`src/Neuron/Collections/ErrorCollection.php`) - Error message collection

### Security
- **SimpleCrypt** (`src/Neuron/Encryption/SimpleCrypt.php`) - AES-256-CBC encryption/decryption
- **TokenGenerator** (`src/Neuron/Tools/TokenGenerator.php`) - Random token generation

### Filtering
- **Filter Parser/Scanner** (`src/Neuron/Filter/`) - Expression-based filtering with context support

## Testing
- Tests are in `tests/` directory using PHPUnit 10/11
- Bootstrap in `tests/bootstrap.php`
- Database tests are grouped with `#[Group('database')]` and excluded from CI
- Run tests: `vendor/bin/phpunit --exclude-group=database`

## Build & Dependencies
- PHP >= 8.1
- Composer for dependency management
- Key dependencies: `nesbot/carbon`, `ext-gettext`
- Dev dependency: `phpunit/phpunit`
36 changes: 36 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Tests

on:
push:
branches: [ master, main ]
pull_request:
branches: [ master, main ]

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
php-version: ['8.1', '8.2', '8.3']

name: PHP ${{ matrix.php-version }}

steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: gettext, openssl, mbstring
coverage: xdebug

- name: Install dependencies
run: composer install --prefer-dist --no-progress

- name: Run tests
run: vendor/bin/phpunit --exclude-group=database
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea/
vendor/
composer.lock
composer.lock
.phpunit.cache
43 changes: 43 additions & 0 deletions claude.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Claude AI Assistant Guide for Neuron Framework

This document provides context for AI assistants working with the Neuron framework codebase.

## Project Documentation

- [Project Summary](.ai/project-summary.md) - Architecture overview and component descriptions
- [Coding Conventions](.ai/conventions.md) - Code style, patterns, and testing practices

## Quick Start

### Install Dependencies
```bash
composer install
```

### Run Tests
```bash
# Run all tests (excluding database-dependent tests)
vendor/bin/phpunit --exclude-group=database

# Run specific test file
vendor/bin/phpunit tests/ToolsTest.php

# Run with coverage
vendor/bin/phpunit --exclude-group=database --coverage-text
```

## Key Areas

### Input Validation (`src/Neuron/Core/Tools.php`)
The primary input validation layer. All user input should be validated through `Tools::checkInput()` before use. The `Tools::getInput()` method combines validation with data retrieval and type-specific processing.

**Important**: Date validation uses `ctype_digit()` and `checkdate()` to ensure all date parts are valid integers representing a real date. The `getInput()` method casts date parts to `(int)` before passing to `mktime()` as a defence-in-depth measure.

### Database Queries (`src/Neuron/DB/Query.php`)
Always use parameterized queries via the `Query` class to prevent SQL injection. Never concatenate user input directly into SQL strings.

### Testing
Tests are located in `tests/` and use PHPUnit. Database-dependent tests are grouped with `#[Group('database')]` and require a MySQL connection. CI runs tests excluding this group.

## CI/CD
GitHub Actions workflow runs tests on PHP 8.1, 8.2, and 8.3. See `.github/workflows/tests.yml`.
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,24 @@
],

"require" : {
"php": ">=5.5.0",
"php": ">=8.1.0",
"ext-gettext" : "*",
"nesbot/carbon": "~1.18"
"nesbot/carbon": "^2.0||^3.0"
},

"require-dev": {
"phpunit/phpunit": "5.1.*"
"phpunit/phpunit": "^10.0||^11.0"
},

"autoload": {
"psr-4" : {
"Neuron\\" : "src/Neuron/"
}
},

"autoload-dev": {
"psr-4": {
"Neuron\\Tests\\" : "tests/"
}
}
}
12 changes: 7 additions & 5 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php">
<phpunit bootstrap="tests/bootstrap.php"
colors="true"
cacheDirectory=".phpunit.cache">

<filter>
<whitelist>
<source>
<include>
<directory>src/Neuron</directory>
</whitelist>
</filter>
</include>
</source>

<testsuites>
<testsuite name="Neuron Test Suite">
Expand Down
13 changes: 10 additions & 3 deletions src/Neuron/Core/Tools.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static function getInput ($dat, $key, $type, $default = null)
// For date's return timestamp.
case 'date':
$time = explode ('-', $dat[$key]);
return mktime (0, 0, 1, $time[1], $time[2], $time[0]);
return mktime (0, 0, 1, (int)$time[1], (int)$time[2], (int)$time[0]);

case 'datetime':
return new DateTime ($dat[$key]);
Expand Down Expand Up @@ -106,8 +106,15 @@ public static function checkInput ($value, $type)

elseif ($type == 'date')
{
$time = explode ('-', $value);
return self::isValidUTF8 ($value) && (count ($time) == 3);
if (!self::isValidUTF8($value)) {
return false;
}
$time = explode('-', $value);
return count($time) === 3
&& ctype_digit($time[0])
&& ctype_digit($time[1])
&& ctype_digit($time[2])
&& checkdate((int)$time[1], (int)$time[2], (int)$time[0]);
}

elseif ($type == 'datetime') {
Expand Down
15 changes: 15 additions & 0 deletions src/Neuron/DB/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,26 @@ public function setLogger (Logger $logger)
$this->logger = $logger;
}

/** @var Database|null Test-only override, set via setInstance() */
private static $testInstance = null;

/**
* Override the singleton instance for testing purposes.
* @param Database|null $instance
*/
public static function setInstance (?Database $instance)
{
self::$testInstance = $instance;
}

/**
* @return Database
*/
public static function getInstance ()
{
if (self::$testInstance !== null) {
return self::$testInstance;
}
return self::__getInstance ();
}

Expand Down
Loading