Skip to content

Commit 902bd3e

Browse files
committed
2 parents 18d8b69 + 888c0d3 commit 902bd3e

73 files changed

Lines changed: 7090 additions & 515 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.docker

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# .env.docker – Copy to .env to override default ports in docker-compose.yml
2+
3+
# MySQL host port (default: 3306)
4+
# MYSQL_PORT=3307
5+
6+
# PostgreSQL host port (default: 5432)
7+
# PGSQL_PORT=5433
8+
9+
# Redis host port (default: 6379)
10+
# REDIS_PORT=6380
11+
12+
# Memcached host port (default: 11211)
13+
# MEMCACHED_PORT=11212

.gitattributes

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
/tmp export-ignore
1+
w/tmp export-ignore
22
/.gitattributes export-ignore
33
/.gitignore export-ignore
44
/.travis.yml export-ignore
55
/.github export-ignore
66
/package.json export-ignore
77
/phpunit.travis.xml export-ignore
88
/phpunit.xml.dist export-ignore
9+
/docker export-ignore
10+
/docker-compose.yml export-ignore
11+
/docker-compose.override.yml.dist export-ignore
12+
/.env.docker export-ignore
913
/packages/*/test export-ignore
1014
/packages/*/.gitattributes export-ignore
1115
/packages/*/.gitignore export-ignore

.github/copilot-instructions.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copilot Instructions
2+
3+
## General Guidelines
4+
5+
See `/AGENTS.md` for general guidelines on how to use Copilot effectively.
6+
7+
## Others
8+
9+
- Global Code Style: See `/.github/instructions/cs.instructions.md` for advanced code style instructions.
10+
- Testing Code Style: See `/.github/instructions/test.instructions.md` for testing-specific code style instructions.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Advanced Code Style Instructions
2+
3+
## Use New without parentheses in PHP 8.4
4+
5+
Bad
6+
7+
```php
8+
(new FooBar()).run();
9+
```
10+
11+
Good
12+
13+
```php
14+
new FooBar()->run();
15+
```
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
applyTo: "**/{test,Test,tests,Tests}/**/*.php"
3+
---
4+
5+
# Testing Instructions
6+
7+
## PHPUnit Mock – Invocation Count Matchers
8+
9+
Use `$this->` instead of `self::` for all count matchers.
10+
11+
```php
12+
// Bad
13+
$mock->expects(self::once())->method('foo');
14+
15+
// Good
16+
$mock->expects($this->once())->method('foo');
17+
```
18+
19+
Applies to: `once()`, `never()`, `any()`, `exactly($n)`, `atLeastOnce()`, `atMost($n)`.
20+

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,9 @@ phpunit.xml
2727
.phpunit.cache
2828
.scannerwork
2929

30+
# Docker #
31+
docker-compose.override.yml
32+
.env
33+
3034
# Extra #
3135
!.gitkeep

AGENTS.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Windwalker Framework – Agent Guide
2+
3+
## Architecture Overview
4+
5+
**Monorepo of 26+ standalone PHP packages** under `packages/`. Each package is independently installable via Composer
6+
but shares a unified dev environment at the root. The root `composer.json` maps all namespace prefixes (
7+
`Windwalker\{PackageName}\`) and autoloads each package's `src/bootstrap.php`.
8+
9+
This repository ships the **components** consumed by the full Windwalker framework (`windwalker/windwalker`). It is not
10+
a runnable application.
11+
12+
**PHP requirement:** ≥ 8.4.6. Code uses PHP 8.4 features (asymmetric visibility `public protected(set)`, named
13+
arguments, first-class callables).
14+
15+
## Code Style
16+
17+
- PSR-12 coding style.
18+
- Strict types (`declare(strict_types=1);` in all source files).
19+
- Docblocks only for non-obvious code; no redundant `@param`/`@return` when types are clear from signatures.
20+
- No global state or singletons; dependencies injected via constructors or method parameters.
21+
- No static methods except for pure utility functions (e.g. `StrInflector`, `Arr` or `Str`).
22+
- No facades or service locators; use explicit class references and dependency injection.
23+
- No global functions except for namespaced helpers defined in `functions.php` (e.g. `\Windwalker\collect()`,
24+
`\Windwalker\raw()`). These are autoloaded via Composer's `files` autoloading and are not procedural global functions.
25+
- No magic methods (`__call`, `__get`, etc.) – all behavior should be explicit and discoverable via class methods and
26+
properties.
27+
- No deprecated features or legacy patterns; the codebase is modern PHP 8.4+ and should not contain any legacy PHP 5/7
28+
constructs.
29+
- Use PHP 8.5 property hooks with asymmetric visibility (`public protected(set)`) for properties prior than legacy
30+
getter/setter methods. This allows read-only public access while still allowing internal mutation when necessary.
31+
32+
All code style instructions see: `/.github/instructions/cs.instructions.md`.
33+
34+
All test code style instructions see: `/.github/instructions/test.instructions.md`.
35+
36+
## Package Layout
37+
38+
Every package follows this structure:
39+
40+
```
41+
packages/{name}/
42+
src/ # PSR-4 source (Windwalker\{Name}\)
43+
src/bootstrap.php # Loaded by Composer autoload files – registers closures/helpers
44+
src/functions.php # Global helper functions (e.g. \Windwalker\collect(), \Windwalker\raw())
45+
test/ # PHPUnit tests (Windwalker\{Name}\Test\)
46+
composer.json # Standalone package metadata
47+
phpunit.xml.dist # Per-package PHPUnit config
48+
```
49+
50+
All source files begin with `declare(strict_types=1);`.
51+
52+
## Developer Workflows
53+
54+
### Running Tests
55+
56+
```bash
57+
# All enabled tests (edit phpunit.xml to uncomment suites)
58+
php vendor/bin/phpunit
59+
60+
# Single package suite
61+
php vendor/bin/phpunit --configuration packages/orm/phpunit.xml.dist
62+
63+
# Database/HTTP tests require setup first:
64+
php -S localhost:8000 bin/test-server.php # HTTP test server
65+
# Set WINDWALKER_TEST_DB_DSN_MYSQL in phpunit.xml
66+
```
67+
68+
The root `phpunit.xml` is copied from `phpunit.xml.dist` and can be edited to enable/disable test suites. Each package
69+
also has its own `phpunit.xml.dist` for package-specific configuration (e.g. database DSN).
70+
71+
### Test Base Classes
72+
73+
- DB tests extend `AbstractDatabaseTestCase` (in `packages/database/src/Test/`).
74+
- ORM tests extend `AbstractORMTestCase` which wires `ORM` to a live DB adapter.
75+
- Executed SQL is logged to `packages/database/tmp/test-sql.sql` during test runs.
76+
77+
## Project-Specific Conventions
78+
79+
- **Global helpers** are namespaced functions, not procedural: e.g. `\Windwalker\collect([...])`,
80+
`\Windwalker\raw($sql)`. Defined in `functions.php`, auto-loaded.
81+
- **Bootstrap files** (`src/bootstrap.php`) use autoload `files` – do not put heavy logic there; they mostly declare
82+
global function aliases.
83+
- **Deprecated options key** for some array or int options has moved to `***Options` classes (e.g. `ORM::FOR_UPDATE`
84+
`new ORMOptions(forUpdate: true)`) – the old constants still exist but are marked deprecated.
85+
- **StrInflector** (`packages/utilities/src/StrInflector.php`) is used project-wide for singular/plural table alias
86+
resolution (e.g. `Table` attribute alias defaults to `StrInflector::toSingular($tableName)`).
87+
- Each package's `composer.json` is also listed under `"replace"` in the root – this lets Composer treat the monorepo
88+
root as all packages simultaneously.

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@
7171
"asika/simple-benchmark": "^3.0",
7272
"rize/uri-template": "^0.3.5||^0.4.0",
7373
"guzzlehttp/uri-template": "^1.0",
74-
"asika/better-units": "^0.1.1"
74+
"asika/better-units": "^0.1.1",
75+
"symfony/cache": "^8.0"
7576
},
7677
"suggest": {
7778
"symfony/yaml": "Install ~4.0 if you require YAML support.",

docker-compose.override.yml.dist

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Docker Local Override Configuration
2+
#
3+
# If you already have some services installed locally (e.g. MySQL, Redis), you can
4+
# copy the relevant service block into this file and adjust the ports mapping,
5+
# or remove that service entirely to connect to your local installation instead.
6+
# Update the host in phpunit.xml to localhost / 127.0.0.1 accordingly.
7+
#
8+
# Usage:
9+
# cp docker-compose.override.yml.dist docker-compose.override.yml
10+
#
11+
# Example: remap MySQL to port 3307 to avoid conflicts with a local installation
12+
13+
services:
14+
# Uncomment to override the MySQL port (or remove the service to skip Docker MySQL)
15+
# mysql:
16+
# ports:
17+
# - "3307:3306"
18+
# profiles:
19+
# - disabled
20+
21+
# postgresql:
22+
# ports:
23+
# - "5433:5432"
24+
# profiles:
25+
# - disabled
26+
27+
# redis:
28+
# ports:
29+
# - "6380:6379"
30+
# profiles:
31+
# - disabled
32+
33+
# memcached:
34+
# ports:
35+
# - "11212:11211"
36+
# profiles:
37+
# - disabled

docker-compose.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
services:
2+
mysql:
3+
image: mysql:8.4
4+
container_name: windwalker_mysql
5+
environment:
6+
MYSQL_ROOT_PASSWORD: ut1234
7+
MYSQL_DATABASE: windwalker_test
8+
ports:
9+
- "${MYSQL_PORT:-3306}:3306"
10+
volumes:
11+
- mysql_data:/var/lib/mysql
12+
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/windwalker.cnf:ro
13+
healthcheck:
14+
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-ppassword"]
15+
interval: 10s
16+
timeout: 5s
17+
retries: 5
18+
start_period: 30s
19+
20+
postgresql:
21+
image: postgres:17-alpine
22+
container_name: windwalker_postgresql
23+
environment:
24+
POSTGRES_USER: postgres
25+
POSTGRES_PASSWORD: ut1234
26+
POSTGRES_DB: windwalker_test
27+
ports:
28+
- "${PGSQL_PORT:-5432}:5432"
29+
volumes:
30+
- postgresql_data:/var/lib/postgresql/data
31+
healthcheck:
32+
test: ["CMD-SHELL", "pg_isready -U postgres"]
33+
interval: 10s
34+
timeout: 5s
35+
retries: 5
36+
start_period: 15s
37+
38+
redis:
39+
image: redis:7-alpine
40+
container_name: windwalker_redis
41+
ports:
42+
- "${REDIS_PORT:-6379}:6379"
43+
volumes:
44+
- redis_data:/data
45+
healthcheck:
46+
test: ["CMD", "redis-cli", "ping"]
47+
interval: 10s
48+
timeout: 3s
49+
retries: 5
50+
51+
memcached:
52+
image: memcached:1-alpine
53+
container_name: windwalker_memcached
54+
ports:
55+
- "${MEMCACHED_PORT:-11211}:11211"
56+
57+
volumes:
58+
mysql_data:
59+
postgresql_data:
60+
redis_data:
61+

0 commit comments

Comments
 (0)