Skip to content

Commit 981b501

Browse files
committed
added CLAUDE.md
1 parent 2979472 commit 981b501

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

CLAUDE.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is **nette/component-model**, a foundational library providing the component architecture for the Nette Framework. It implements a hierarchical component system where components can be nested within containers, monitored for attach/detach events, and accessed through a path-based lookup system.
8+
9+
**Requirements:** PHP 8.2 - 8.5
10+
11+
## Essential Commands
12+
13+
### Testing
14+
```bash
15+
# Run all tests
16+
composer tester
17+
# or directly:
18+
vendor/bin/tester tests -s -C
19+
20+
# Run specific test file
21+
php tests/ComponentModel/Container.getComponents.phpt
22+
23+
# Run tests in specific directory
24+
vendor/bin/tester tests/ComponentModel -s -C
25+
```
26+
27+
### Static Analysis
28+
```bash
29+
# Run PHPStan (level 8)
30+
composer phpstan
31+
# or directly:
32+
vendor/bin/phpstan analyse
33+
```
34+
35+
## Architecture Overview
36+
37+
### Core Classes and Interfaces
38+
39+
The library consists of 5 primary files in `src/ComponentModel/`:
40+
41+
1. **IComponent** - Base interface defining core component functionality
42+
- `getName()`, `getParent()`, `setParent()`
43+
- Defines `NameSeparator` constant (`-`) for component path construction
44+
45+
2. **IContainer** - Interface for components that can contain child components
46+
- `addComponent()`, `removeComponent()`, `getComponent()`, `getComponents()`
47+
- Generic typed: `@template T of IComponent`
48+
49+
3. **Component** - Abstract base class implementing IComponent
50+
- Provides parent-child relationship management
51+
- Implements **monitoring system** for ancestor attach/detach events
52+
- `lookup()` - finds closest ancestor of specified type
53+
- `lookupPath()` - returns path from ancestor to this component
54+
- `monitor()` - registers callbacks for when component is attached/detached to ancestor of specific type
55+
- Uses SmartObject trait from nette/utils
56+
57+
4. **Container** - Concrete implementation of IContainer extending Component
58+
- Manages child component collection (`$components` array)
59+
- Implements **factory pattern**: `createComponent($name)` delegates to `createComponent<Name>()` methods
60+
- `getComponent()` - retrieves or auto-creates components via factory methods
61+
- `getComponents()` - returns immediate children (deprecated parameters for recursive/filter)
62+
- `getComponentTree()` - returns flattened depth-first list of all nested components
63+
- Handles cloning of component trees
64+
65+
5. **ArrayAccess** - Trait providing array-like access to container components
66+
- `$container['name']` maps to `$container->getComponent('name')`
67+
- Allows `$container['name'] = $component` syntax
68+
69+
### Key Architectural Concepts
70+
71+
#### Component Hierarchy and Paths
72+
Components form a tree structure. Each component has:
73+
- A parent (IContainer or null for root)
74+
- A name (string or null for root)
75+
- A path constructed with `-` separator (e.g., `form-fieldset-name`)
76+
77+
#### Factory Pattern for Lazy Component Creation
78+
Containers check for `createComponent<Name>()` methods when `getComponent()` is called:
79+
```php
80+
protected function createComponentButton($name): Button
81+
{
82+
return new Button();
83+
}
84+
// Now $container->getComponent('button') auto-creates if doesn't exist
85+
```
86+
87+
#### Monitoring System
88+
Components can register callbacks to be notified when attached/detached to ancestors:
89+
```php
90+
$component->monitor(Form::class,
91+
attached: fn(Form $form) => $this->form = $form,
92+
detached: fn(Form $form) => $this->form = null
93+
);
94+
```
95+
This is internally used for `lookup()` optimization and enables reactive component behavior.
96+
97+
#### Component Validation Hooks
98+
- `validateParent()` - override to restrict what containers a component can be added to
99+
- `validateChildComponent()` - override to restrict what components can be added to a container
100+
101+
### Recent Breaking Changes
102+
103+
The codebase has recently undergone API cleanup:
104+
105+
1. **Container::getComponents()** - Parameters removed
106+
- Old: `getComponents(bool $recursive, string $filterType)`
107+
- New: `getComponents()` - returns only immediate children
108+
- Use `getComponentTree()` instead for recursive traversal
109+
110+
## Test Structure
111+
112+
Tests use **Nette Tester** with `.phpt` extension. Each test file:
113+
- Includes `tests/bootstrap.php` which sets up autoloading
114+
- Uses `test()` function for individual test cases (from Tester 2.5+)
115+
- Uses `Assert` class for assertions
116+
- Often creates minimal test classes (Button, ComponentX) within the test file
117+
118+
Example test pattern:
119+
```php
120+
<?php
121+
declare(strict_types=1);
122+
use Tester\Assert;
123+
require __DIR__ . '/../bootstrap.php';
124+
125+
test('description of what is tested', function () {
126+
$container = new Container;
127+
// test code
128+
Assert::same('expected', $actual);
129+
});
130+
```
131+
132+
The `Notes` class in bootstrap.php is a test helper for collecting messages during component lifecycle events.
133+
134+
## Development Notes
135+
136+
- All files must have `declare(strict_types=1)`
137+
- PHPStan runs at level 8 (strictest)
138+
- CI tests against PHP 8.2, 8.3, 8.4, and 8.5
139+
- The project uses classmap + PSR-4 autoloading for `Nette\` namespace
140+
- Components cannot be serialized (`__serialize()` throws exception)
141+
- Cloning properly deep-clones entire component trees

0 commit comments

Comments
 (0)