Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:43:22 +08:00
commit aab6ef2415
31 changed files with 12720 additions and 0 deletions

View File

@@ -0,0 +1,621 @@
# Directory Structure Standards
**Purpose:** Validate proper separation of committed configuration vs generated/temporary files in TYPO3 extensions
## Why Directory Structure Matters
Proper directory organization prevents common issues:
-**Version Control Hygiene** - Only configuration committed, not generated files
-**Build Reproducibility** - Clean installs work without artifacts
-**CI/CD Clarity** - Clear separation of what's tracked vs generated
-**Onboarding Efficiency** - New contributors understand structure instantly
-**Maintenance Simplicity** - Updates don't conflict with local artifacts
Without proper structure:
- ❌ Bloated repositories with vendor/, cache files committed
- ❌ Git conflicts in generated files
- ❌ CI failures from missing .gitignore patterns
- ❌ Confusion about what files are source vs generated
## TYPO3 Standard Directory Pattern
### Build/ - Committed Configuration
**Purpose:** Project-specific configuration files that define how to build, test, and validate code
**Characteristics:**
- ✅ Committed to git
- ✅ Shared across all developers
- ✅ Version controlled
- ✅ Defines project standards
**Standard Contents:**
```
Build/
├── phpstan.neon # Static analysis config
├── phpstan-baseline.neon # Known issues baseline (optional)
├── php-cs-fixer.php # Code style config
├── rector.php # Refactoring rules (optional, can be in Build/rector/)
├── phpunit/
│ ├── UnitTests.xml # Unit test configuration
│ ├── FunctionalTests.xml # Functional test configuration
│ └── bootstrap.php # Test bootstrap (if needed)
└── Scripts/
└── runTests.sh # Test orchestration script
```
**Alternative Rector Location:**
```
Build/
└── rector/
└── rector.php # Rector config in subdirectory
```
**Git Status:** All files tracked (not in .gitignore)
### .Build/ - Generated/Temporary Files
**Purpose:** Composer-generated files, caches, runtime artifacts, test outputs
**Characteristics:**
- ❌ NOT committed to git (gitignored)
- ✅ Generated by composer/build tools
- ✅ Recreatable from configuration
- ✅ Developer-specific caches allowed
**Standard Contents:**
```
.Build/
├── bin/ # Composer bin-dir (phpunit, phpstan, etc.)
├── public/ # Web root (TYPO3 web-dir)
│ ├── index.php
│ ├── typo3/
│ └── typo3conf/
├── vendor/ # Composer dependencies
├── .php-cs-fixer.cache # php-cs-fixer cache file
├── .phpunit.result.cache # PHPUnit cache
└── var/ # Runtime cache/logs (optional)
```
**Git Status:** Entire directory in .gitignore
**Standard .gitignore Entry:**
```gitignore
# Composer generated files
.Build/
```
## Validation Checklist
### 1. Build/ Directory Structure
**Check for committed configuration files:**
```bash
ls -la Build/
```
**Required files for comprehensive quality:**
- `Build/phpstan.neon` - Static analysis configuration
- `Build/php-cs-fixer.php` - Code style configuration
- `Build/phpunit/UnitTests.xml` - Unit test configuration
- `Build/Scripts/runTests.sh` - Test orchestration
**Optional but recommended:**
- `Build/phpunit/FunctionalTests.xml` - Functional test configuration
- `Build/phpstan-baseline.neon` - Known issues baseline
- `Build/rector.php` or `Build/rector/rector.php` - Refactoring rules
**Severity if missing:** 🟡 **Medium** - Quality tools not standardized
### 2. .Build/ Directory Gitignore
**Check .gitignore for .Build/ exclusion:**
```bash
grep -E '^\\.Build/' .gitignore
```
**Expected pattern:**
```gitignore
.Build/
```
**Alternative patterns (also valid):**
```gitignore
/.Build/
.Build/*
```
**Check for accidental commits:**
```bash
git ls-files .Build/
# Should return empty - no files from .Build/ should be tracked
```
**Severity if misconfigured:** 🔴 **High** - Can lead to repository bloat
### 3. Composer Configuration Alignment
**Validate composer.json paths match directory structure:**
```bash
# Extract composer paths
cat composer.json | jq -r '.config."bin-dir"' # Should be .Build/bin
cat composer.json | jq -r '.config."vendor-dir"' # Should be .Build/vendor
cat composer.json | jq -r '.extra.typo3.cms."web-dir"' # Should be .Build/public
```
**Expected composer.json:**
```json
{
"config": {
"vendor-dir": ".Build/vendor",
"bin-dir": ".Build/bin"
},
"extra": {
"typo3/cms": {
"web-dir": ".Build/public"
}
}
}
```
**Severity if mismatched:** 🔴 **High** - Build will fail or create wrong structure
### 4. Quality Tool Configuration Paths
**Validate tool configs reference correct cache locations:**
```bash
# Check PHPUnit cache location
grep -r "\.phpunit\.result\.cache" Build/phpunit/*.xml
# Should reference .Build/.phpunit.result.cache or no cache directive
# Check php-cs-fixer cache
grep -r "cache-file" composer.json Build/php-cs-fixer.php
# Should reference .Build/.php-cs-fixer.cache if specified
# Check PHPStan cache (usually auto-managed)
grep -r "tmpDir" Build/phpstan.neon
# Should reference .Build/phpstan if specified, or auto temp
```
**Example CORRECT patterns:**
```json
// composer.json
{
"scripts": {
"ci:cgl": [
"php-cs-fixer fix --cache-file .Build/.php-cs-fixer.cache --dry-run --diff"
]
}
}
```
```php
// Build/php-cs-fixer.php
return (new PhpCsFixer\Config())
->setCacheFile('.Build/.php-cs-fixer.cache')
->setRules([...]);
```
```neon
# Build/phpstan.neon
parameters:
tmpDir: .Build/phpstan
```
**Severity if wrong:** 🟡 **Medium** - Works but creates clutter in Build/
### 5. Tea Extension Reference
**Source:** https://github.com/TYPO3BestPractices/tea
**Tea Directory Structure:**
```
tea/
├── .gitignore # Excludes .Build/
├── Build/
│ ├── phpstan.neon
│ ├── phpstan-baseline.neon
│ ├── php-cs-fixer.php
│ ├── phpunit/
│ │ ├── FunctionalTests.xml
│ │ └── UnitTests.xml
│ └── Scripts/
│ └── runTests.sh
├── .Build/ # Gitignored, generated by composer
│ ├── bin/
│ ├── public/
│ └── vendor/
└── composer.json # Defines .Build/ paths
```
**Tea .gitignore (relevant excerpt):**
```gitignore
# Composer-generated files
.Build/
composer.lock
```
**Tea composer.json (relevant excerpt):**
```json
{
"config": {
"vendor-dir": ".Build/vendor",
"bin-dir": ".Build/bin"
},
"extra": {
"typo3/cms": {
"web-dir": ".Build/public"
}
}
}
```
## Common Issues and Fixes
### Issue 1: Cache Files in Build/ Directory
**Diagnosis:**
```bash
ls -la Build/.php-cs-fixer.cache Build/.phpunit.result.cache
# If these files exist, they're in the WRONG location
```
**Problem:** Cache files committed or in wrong directory
**Fix:**
```bash
# Remove from wrong location
rm Build/.php-cs-fixer.cache Build/.phpunit.result.cache
# Update configuration to use .Build/
```
**Update php-cs-fixer config:**
```php
// Build/php-cs-fixer.php
return (new PhpCsFixer\Config())
->setCacheFile('.Build/.php-cs-fixer.cache') // ✅ Correct location
// ...
```
**Update composer scripts:**
```json
{
"scripts": {
"ci:cgl": [
"php-cs-fixer fix --cache-file .Build/.php-cs-fixer.cache --dry-run --diff"
]
}
}
```
### Issue 2: .Build/ Files Committed to Git
**Diagnosis:**
```bash
git ls-files .Build/
# Should be empty
```
**Problem:** Generated files tracked in git (vendor/, bin/, etc.)
**Fix:**
```bash
# Remove from git tracking
git rm -r --cached .Build/
# Ensure .gitignore has entry
echo ".Build/" >> .gitignore
# Commit the cleanup
git add .gitignore
git commit -m "fix: remove .Build/ from git tracking, add to .gitignore"
```
### Issue 3: Missing Build/ Directory
**Diagnosis:**
```bash
ls -la Build/
# Directory doesn't exist
```
**Problem:** No standardized quality tool configuration
**Fix:**
```bash
# Create Build/ directory structure
mkdir -p Build/{phpunit,Scripts}
# Add quality tool configs (see templates below)
# Then commit
git add Build/
git commit -m "feat: add Build/ directory with quality tool configurations"
```
### Issue 4: Rector in Wrong Location
**Diagnosis:**
```bash
# Check for rector.php in project root
ls -la rector.php
# Should be in Build/ or Build/rector/ instead
```
**Problem:** Configuration file in project root instead of Build/
**Fix:**
```bash
# Option 1: Move to Build/
mv rector.php Build/rector.php
# Option 2: Move to Build/rector/ (preferred for complex configs)
mkdir -p Build/rector
mv rector.php Build/rector/rector.php
# Update paths in rector.php
# Then commit
git add Build/
git rm rector.php
git commit -m "refactor: move rector config to Build/ directory"
```
## Conformance Report Integration
### When Evaluating Directory Structure:
**In "Best Practices" Section:**
```markdown
### Directory Structure
**Analysis:**
- ✅ Build/ directory present with committed configurations
- ✅ Build/phpstan.neon, Build/php-cs-fixer.php present
- ✅ Build/phpunit/ directory with test configs
- ✅ Build/Scripts/runTests.sh present
- ✅ .Build/ properly gitignored (entire directory)
- ✅ Composer paths correctly reference .Build/
- ✅ Cache files located in .Build/, not Build/
- ✅ No .Build/ files committed to git
**Or with issues:**
- ❌ Cache files in wrong location
- Files: Build/.php-cs-fixer.cache, Build/.phpunit.result.cache
- Expected: .Build/.php-cs-fixer.cache, .Build/.phpunit.result.cache
- Severity: Medium
- Fix: Move cache files to .Build/ and update configs
- ❌ .Build/ files committed to git
- Files: .Build/vendor/, .Build/bin/
- Command: `git ls-files .Build/` shows tracked files
- Severity: High
- Fix: `git rm -r --cached .Build/` and ensure .gitignore has `.Build/`
- ⚠️ Missing Build/ directory
- Impact: No standardized quality tool configuration
- Severity: Medium
- Recommendation: Create Build/ with phpstan.neon, php-cs-fixer.php, phpunit configs
```
## Scoring Impact
**Best Practices Score Deductions:**
| Issue | Severity | Score Impact |
|-------|----------|--------------|
| .Build/ files committed | High | -4 points |
| Cache files in Build/ | Medium | -2 points |
| Missing .gitignore for .Build/ | High | -3 points |
| Composer paths don't match structure | High | -3 points |
| Missing Build/ directory | Medium | -2 points |
| Rector/configs in project root | Low | -1 point |
**Maximum deduction for directory issues:** -6 points (out of 20 for Best Practices)
## Automated Validation Script
Create `scripts/validate-directory-structure.sh`:
```bash
#!/bin/bash
set -e
echo "🔍 Validating directory structure..."
ISSUES=0
# Check 1: .Build/ should be gitignored
if ! grep -qE '^\\.Build/' .gitignore; then
echo "❌ .gitignore missing '.Build/' entry"
ISSUES=$((ISSUES + 1))
else
echo "✅ .Build/ properly gitignored"
fi
# Check 2: No .Build/ files should be tracked
TRACKED_BUILD=$(git ls-files .Build/ 2>/dev/null | wc -l)
if [ "${TRACKED_BUILD}" -gt 0 ]; then
echo "❌ .Build/ files are committed to git:"
git ls-files .Build/
ISSUES=$((ISSUES + 1))
else
echo "✅ No .Build/ files tracked in git"
fi
# Check 3: Build/ directory should exist
if [ ! -d "Build" ]; then
echo "⚠️ Build/ directory missing"
ISSUES=$((ISSUES + 1))
else
echo "✅ Build/ directory exists"
# Check for standard files
[ -f "Build/phpstan.neon" ] && echo " ✅ phpstan.neon" || echo " ⚠️ phpstan.neon missing"
[ -f "Build/php-cs-fixer.php" ] && echo " ✅ php-cs-fixer.php" || echo " ⚠️ php-cs-fixer.php missing"
[ -d "Build/phpunit" ] && echo " ✅ phpunit/" || echo " ⚠️ phpunit/ missing"
[ -f "Build/Scripts/runTests.sh" ] && echo " ✅ runTests.sh" || echo " ⚠️ runTests.sh missing"
fi
# Check 4: Cache files should NOT be in Build/
if [ -f "Build/.php-cs-fixer.cache" ] || [ -f "Build/.phpunit.result.cache" ]; then
echo "❌ Cache files in wrong location (Build/ instead of .Build/):"
ls -la Build/.*.cache 2>/dev/null || true
ISSUES=$((ISSUES + 1))
else
echo "✅ No cache files in Build/"
fi
# Check 5: Composer paths should reference .Build/
BIN_DIR=$(jq -r '.config."bin-dir" // ".Build/bin"' composer.json)
VENDOR_DIR=$(jq -r '.config."vendor-dir" // ".Build/vendor"' composer.json)
WEB_DIR=$(jq -r '.extra.typo3.cms."web-dir" // ".Build/public"' composer.json)
if [ "${BIN_DIR}" = ".Build/bin" ]; then
echo "✅ Composer bin-dir: ${BIN_DIR}"
else
echo "⚠️ Composer bin-dir: ${BIN_DIR} (expected .Build/bin)"
ISSUES=$((ISSUES + 1))
fi
if [ "${VENDOR_DIR}" = ".Build/vendor" ]; then
echo "✅ Composer vendor-dir: ${VENDOR_DIR}"
else
echo "⚠️ Composer vendor-dir: ${VENDOR_DIR} (expected .Build/vendor)"
ISSUES=$((ISSUES + 1))
fi
if [ "${WEB_DIR}" = ".Build/public" ]; then
echo "✅ TYPO3 web-dir: ${WEB_DIR}"
else
echo "⚠️ TYPO3 web-dir: ${WEB_DIR} (expected .Build/public)"
ISSUES=$((ISSUES + 1))
fi
echo ""
if [ ${ISSUES} -eq 0 ]; then
echo "✅ Directory structure validation complete - no issues found"
exit 0
else
echo "❌ Directory structure validation found ${ISSUES} issue(s)"
exit 1
fi
```
## Quick Reference Checklist
**When evaluating directory structure:**
```
□ .gitignore contains .Build/ entry
□ Build/ directory exists and contains configs
□ Build/phpstan.neon exists
□ Build/php-cs-fixer.php exists
□ Build/phpunit/ directory exists with XML configs
□ Build/Scripts/runTests.sh exists
□ .Build/ is NOT tracked in git (git ls-files .Build/ is empty)
□ Cache files are in .Build/, not Build/
□ Composer bin-dir = .Build/bin
□ Composer vendor-dir = .Build/vendor
□ TYPO3 web-dir = .Build/public
□ No configuration files in project root (rector.php, phpstan.neon, etc.)
```
## Configuration File Templates
### Build/phpstan.neon
```neon
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
- vendor/saschaegerer/phpstan-typo3/extension.neon
parameters:
level: max
paths:
- Classes
- Tests
tmpDir: .Build/phpstan
reportUnmatchedIgnoredErrors: true
```
### Build/php-cs-fixer.php
```php
<?php
declare(strict_types=1);
$finder = (new PhpCsFixer\Finder())
->in(__DIR__ . '/../Classes')
->in(__DIR__ . '/../Tests');
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
'@PhpCsFixer' => true,
'declare_strict_types' => true,
])
->setCacheFile('.Build/.php-cs-fixer.cache')
->setRiskyAllowed(true)
->setFinder($finder);
```
### Build/rector/rector.php
```php
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;
use Ssch\TYPO3Rector\Set\Typo3LevelSetList;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/../../Classes/',
__DIR__ . '/../../Tests/',
])
->withPhpVersion(PhpVersion::PHP_82)
->withPhpSets(true)
->withSets([
Typo3LevelSetList::UP_TO_TYPO3_13,
]);
```
## Resources
- **Tea Extension Structure:** https://github.com/TYPO3BestPractices/tea
- **Composer Documentation:** https://getcomposer.org/doc/06-config.md
- **TYPO3 Extension Structure:** https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/FileStructure/