611 lines
14 KiB
Markdown
611 lines
14 KiB
Markdown
# ext_emconf.php Validation Standards (TYPO3 v13)
|
|
|
|
**Source:** TYPO3 Core API Reference v13.4 - FileStructure/ExtEmconf.html
|
|
**Purpose:** Complete validation rules for ext_emconf.php including critical TER restrictions
|
|
|
|
## CRITICAL RESTRICTIONS
|
|
|
|
### ❌ MUST NOT use declare(strict_types=1)
|
|
|
|
**CRITICAL:** The TYPO3 Extension Repository (TER) upload **WILL FAIL** if `declare(strict_types=1)` is present in ext_emconf.php.
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
<?php
|
|
declare(strict_types=1);
|
|
$EM_CONF[$_EXTKEY] = [
|
|
// configuration
|
|
];
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
<?php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
// configuration
|
|
];
|
|
```
|
|
|
|
**Detection:**
|
|
```bash
|
|
grep "declare(strict_types" ext_emconf.php && echo "❌ CRITICAL: TER upload will FAIL" || echo "✅ No strict_types"
|
|
```
|
|
|
|
### ✅ MUST use $_EXTKEY variable
|
|
|
|
Extensions must reference the global `$_EXTKEY` variable, not hardcode the extension key.
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
$EM_CONF['my_extension'] = [
|
|
// configuration
|
|
];
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
// configuration
|
|
];
|
|
```
|
|
|
|
**Detection:**
|
|
```bash
|
|
grep '\$EM_CONF\[$_EXTKEY\]' ext_emconf.php && echo "✅ Uses $_EXTKEY" || echo "❌ Hardcoded key"
|
|
```
|
|
|
|
### ❌ MUST NOT contain custom code
|
|
|
|
The ext_emconf.php file must only contain the `$EM_CONF` array assignment. No additional functions, classes, or executable code is allowed.
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
<?php
|
|
function getVersion() { return '1.0.0'; }
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'version' => getVersion(),
|
|
];
|
|
```
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
<?php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'title' => 'My Extension',
|
|
];
|
|
// Additional initialization code
|
|
require_once 'setup.php';
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
<?php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'title' => 'My Extension',
|
|
'version' => '1.0.0',
|
|
];
|
|
```
|
|
|
|
**Detection:**
|
|
```bash
|
|
# Check for function/class definitions
|
|
grep -E '^(function|class|interface|trait|require|include)' ext_emconf.php && echo "❌ Contains custom code" || echo "✅ No custom code"
|
|
```
|
|
|
|
---
|
|
|
|
## Mandatory Fields
|
|
|
|
### title
|
|
**Format:** English extension name
|
|
|
|
**Example:**
|
|
```php
|
|
'title' => 'My Extension',
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep "'title' =>" ext_emconf.php && echo "✅ Has title" || echo "❌ Missing title"
|
|
```
|
|
|
|
### description
|
|
**Format:** Short, precise English description of extension functionality
|
|
|
|
**Requirements:**
|
|
- Clear explanation of what the extension does
|
|
- Should identify the vendor/company for professional extensions
|
|
- Must be meaningful (not just "Extension" or empty)
|
|
- Keep concise but informative (typically 50-150 characters)
|
|
|
|
**Good Examples:**
|
|
```php
|
|
'description' => 'Adds image support to CKEditor5 RTE - by Netresearch',
|
|
'description' => 'Provides advanced content management features for TYPO3 editors',
|
|
'description' => 'Custom form elements for newsletter subscription by Vendor GmbH',
|
|
```
|
|
|
|
**Bad Examples:**
|
|
```php
|
|
'description' => '', // Empty
|
|
'description' => 'Extension', // Too vague
|
|
'description' => 'Some tools', // Meaningless
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
# Check description exists
|
|
grep "'description' =>" ext_emconf.php && echo "✅ Has description" || echo "❌ Missing description"
|
|
|
|
# Check description is not empty or trivial
|
|
DESC=$(grep -oP "'description' => '\K[^']+(?=')" ext_emconf.php)
|
|
[[ ${#DESC} -gt 20 ]] && echo "✅ Description is meaningful" || echo "⚠️ Description too short or vague"
|
|
```
|
|
|
|
### version
|
|
**Format:** `[int].[int].[int]` (semantic versioning)
|
|
|
|
**Examples:**
|
|
- `1.0.0` ✅
|
|
- `2.5.12` ✅
|
|
- `v1.0.0` ❌ (no 'v' prefix)
|
|
- `1.0` ❌ (must have three parts)
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep -oP "'version' => '\K[0-9]+\.[0-9]+\.[0-9]+" ext_emconf.php && echo "✅ Valid version format" || echo "❌ Invalid version"
|
|
```
|
|
|
|
### author
|
|
**Format:** Developer name(s), comma-separated for multiple
|
|
|
|
**Example:**
|
|
```php
|
|
'author' => 'Sebastian Koschel, Sebastian Mendel, Rico Sonntag',
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep "'author' =>" ext_emconf.php && echo "✅ Has author" || echo "❌ Missing author"
|
|
```
|
|
|
|
### author_email
|
|
**Format:** Email address(es), comma-separated for multiple
|
|
|
|
**Example:**
|
|
```php
|
|
'author_email' => 'developer@company.com, other@company.com',
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep "'author_email' =>" ext_emconf.php | grep -q "@" && echo "✅ Has author_email" || echo "❌ Missing author_email"
|
|
```
|
|
|
|
### author_company
|
|
**Format:** Company name
|
|
|
|
**Example:**
|
|
```php
|
|
'author_company' => 'Company Name GmbH',
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep "'author_company' =>" ext_emconf.php && echo "✅ Has author_company" || echo "⚠️ Missing author_company"
|
|
```
|
|
|
|
---
|
|
|
|
## Category Options
|
|
|
|
**Valid categories:**
|
|
|
|
| Category | Purpose |
|
|
|----------|---------|
|
|
| `be` | Backend-oriented functionality |
|
|
| `module` | Backend modules |
|
|
| `fe` | Frontend-oriented functionality |
|
|
| `plugin` | Frontend plugins |
|
|
| `misc` | Miscellaneous utilities |
|
|
| `services` | TYPO3 services |
|
|
| `templates` | Website templates |
|
|
| `example` | Example/demonstration extensions |
|
|
| `doc` | Documentation |
|
|
| `distribution` | Full site distributions/kickstarters |
|
|
|
|
**Example:**
|
|
```php
|
|
'category' => 'fe',
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep -oP "'category' => '\K[a-z]+(?=')" ext_emconf.php | grep -qE '^(be|module|fe|plugin|misc|services|templates|example|doc|distribution)$' && echo "✅ Valid category" || echo "❌ Invalid category"
|
|
```
|
|
|
|
---
|
|
|
|
## State Values
|
|
|
|
**Valid states:**
|
|
|
|
| State | Meaning |
|
|
|-------|---------|
|
|
| `alpha` | Initial development phase, unstable |
|
|
| `beta` | Functional but incomplete or under active development |
|
|
| `stable` | Production-ready (author commits to maintenance) |
|
|
| `experimental` | Exploratory work, may be abandoned |
|
|
| `test` | Demonstration or testing purposes only |
|
|
| `obsolete` | Deprecated or unmaintained |
|
|
| `excludeFromUpdates` | Prevents Extension Manager from updating |
|
|
|
|
**Example:**
|
|
```php
|
|
'state' => 'stable',
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep -oP "'state' => '\K[a-z]+(?=')" ext_emconf.php | grep -qE '^(alpha|beta|stable|experimental|test|obsolete|excludeFromUpdates)$' && echo "✅ Valid state" || echo "❌ Invalid state"
|
|
```
|
|
|
|
---
|
|
|
|
## Constraints Structure
|
|
|
|
### Format
|
|
```php
|
|
'constraints' => [
|
|
'depends' => [
|
|
'typo3' => '13.4.0-13.4.99',
|
|
'php' => '8.2.0-8.4.99',
|
|
],
|
|
'conflicts' => [
|
|
'incompatible_ext' => '',
|
|
],
|
|
'suggests' => [
|
|
'recommended_ext' => '1.0.0-2.99.99',
|
|
],
|
|
],
|
|
```
|
|
|
|
### depends
|
|
**Purpose:** Required dependencies loaded before this extension
|
|
|
|
**Mandatory entries:**
|
|
- `typo3` - TYPO3 version range
|
|
- `php` - PHP version range
|
|
|
|
**Example:**
|
|
```php
|
|
'depends' => [
|
|
'typo3' => '12.4.0-13.4.99',
|
|
'php' => '8.1.0-8.4.99',
|
|
'fluid' => '12.4.0-13.4.99',
|
|
],
|
|
```
|
|
|
|
**Validation:**
|
|
```bash
|
|
grep -A 5 "'depends' =>" ext_emconf.php | grep -q "'typo3'" && echo "✅ TYPO3 dependency" || echo "❌ Missing TYPO3 dep"
|
|
grep -A 5 "'depends' =>" ext_emconf.php | grep -q "'php'" && echo "✅ PHP dependency" || echo "❌ Missing PHP dep"
|
|
```
|
|
|
|
### conflicts
|
|
**Purpose:** Extensions incompatible with this one
|
|
|
|
**Example:**
|
|
```php
|
|
'conflicts' => [
|
|
'old_extension' => '',
|
|
],
|
|
```
|
|
|
|
### suggests
|
|
**Purpose:** Recommended companion extensions (loaded before current extension)
|
|
|
|
**Example:**
|
|
```php
|
|
'suggests' => [
|
|
'news' => '12.1.0-12.99.99',
|
|
],
|
|
```
|
|
|
|
---
|
|
|
|
## Version Constraint Format
|
|
|
|
### TYPO3 Version
|
|
**Format:** `major.minor.patch-major.minor.patch`
|
|
|
|
**Examples:**
|
|
- `12.4.0-12.4.99` - TYPO3 12 LTS only
|
|
- `13.4.0-13.4.99` - TYPO3 13 LTS only
|
|
- `12.4.0-13.4.99` - Both v12 and v13 (recommended for compatibility)
|
|
|
|
### PHP Version
|
|
**Format:** `major.minor.patch-major.minor.patch`
|
|
|
|
**TYPO3 Compatibility:**
|
|
- TYPO3 12 LTS: PHP 8.1-8.4
|
|
- TYPO3 13 LTS: PHP 8.2-8.4
|
|
|
|
**Example:**
|
|
```php
|
|
'php' => '8.1.0-8.4.99', // For v12/v13 compatibility
|
|
'php' => '8.2.0-8.4.99', // For v13 only
|
|
```
|
|
|
|
---
|
|
|
|
## Synchronization with composer.json
|
|
|
|
**Critical:** ext_emconf.php and composer.json must have matching constraints.
|
|
|
|
### Mapping Table
|
|
|
|
| composer.json | ext_emconf.php | Example |
|
|
|--------------|----------------|---------|
|
|
| `"typo3/cms-core": "^12.4 \|\| ^13.4"` | `'typo3' => '12.4.0-13.4.99'` | TYPO3 version |
|
|
| `"php": "^8.1"` | `'php' => '8.1.0-8.4.99'` | PHP version |
|
|
| `"typo3/cms-fluid": "^12.4"` | `'fluid' => '12.4.0-12.4.99'` | Extension dependency |
|
|
|
|
### Validation Strategy
|
|
```bash
|
|
# Compare TYPO3 versions
|
|
COMPOSER_TYPO3=$(jq -r '.require."typo3/cms-core"' composer.json)
|
|
EMCONF_TYPO3=$(grep -oP "'typo3' => '\K[0-9.-]+" ext_emconf.php)
|
|
echo "Composer: $COMPOSER_TYPO3"
|
|
echo "ext_emconf: $EMCONF_TYPO3"
|
|
# Manual comparison required for ^x.y vs x.y.z-x.y.z format
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Required Fields Checklist
|
|
|
|
**Mandatory (MUST have):**
|
|
- [ ] `title` - Extension name in English
|
|
- [ ] `description` - Short, precise description
|
|
- [ ] `version` - Semantic version (x.y.z format)
|
|
- [ ] `category` - Valid category (be, fe, plugin, misc, etc.)
|
|
- [ ] `state` - Valid state (stable, beta, alpha, etc.)
|
|
- [ ] `constraints.depends.typo3` - TYPO3 version range
|
|
- [ ] `constraints.depends.php` - PHP version range
|
|
|
|
**Recommended (SHOULD have):**
|
|
- [ ] `author` - Developer name(s)
|
|
- [ ] `author_email` - Contact email(s)
|
|
- [ ] `author_company` - Company name
|
|
- [ ] `constraints.conflicts` - Conflicting extensions (even if empty array)
|
|
- [ ] `constraints.suggests` - Suggested companion extensions
|
|
|
|
**Complete Example:**
|
|
```php
|
|
<?php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'title' => 'My Extension Title',
|
|
'description' => 'Provides specific functionality for TYPO3.',
|
|
'category' => 'fe',
|
|
'author' => 'Developer Name',
|
|
'author_email' => 'developer@company.com',
|
|
'author_company' => 'Company Name GmbH',
|
|
'state' => 'stable',
|
|
'version' => '1.0.0',
|
|
'constraints' => [
|
|
'depends' => [
|
|
'typo3' => '12.4.0-13.4.99',
|
|
'php' => '8.1.0-8.4.99',
|
|
],
|
|
'conflicts' => [],
|
|
'suggests' => [],
|
|
],
|
|
];
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Validation Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# validate-ext-emconf.sh
|
|
|
|
ERRORS=0
|
|
WARNINGS=0
|
|
|
|
echo "=== ext_emconf.php Validation ===="
|
|
echo ""
|
|
|
|
# CRITICAL: Check for strict_types
|
|
if grep -q "declare(strict_types" ext_emconf.php 2>/dev/null; then
|
|
echo "❌ CRITICAL: ext_emconf.php has declare(strict_types=1)"
|
|
echo " TER upload will FAIL!"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
# CRITICAL: Check for $_EXTKEY usage
|
|
if ! grep -q '\$EM_CONF\[$_EXTKEY\]' ext_emconf.php 2>/dev/null; then
|
|
echo "❌ CRITICAL: Must use \$EM_CONF[\$_EXTKEY], not hardcoded key"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
# CRITICAL: Check for custom code
|
|
if grep -E '^(function|class|interface|trait|require|include)' ext_emconf.php 2>/dev/null; then
|
|
echo "❌ CRITICAL: ext_emconf.php contains custom code (functions/classes/requires)"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
# Check mandatory fields
|
|
grep -q "'title' =>" ext_emconf.php || { echo "❌ Missing title"; ((ERRORS++)); }
|
|
grep -q "'description' =>" ext_emconf.php || { echo "❌ Missing description"; ((ERRORS++)); }
|
|
grep -qP "'version' => '[0-9]+\.[0-9]+\.[0-9]+" ext_emconf.php || { echo "❌ Missing or invalid version"; ((ERRORS++)); }
|
|
|
|
# Check description is meaningful (>20 chars)
|
|
DESC=$(grep -oP "'description' => '\K[^']+(?=')" ext_emconf.php)
|
|
[[ ${#DESC} -lt 20 ]] && { echo "⚠️ Description too short (should be >20 chars)"; ((WARNINGS++)); }
|
|
|
|
# Check category
|
|
CATEGORY=$(grep -oP "'category' => '\K[a-z]+(?=')" ext_emconf.php)
|
|
if [[ ! "$CATEGORY" =~ ^(be|module|fe|plugin|misc|services|templates|example|doc|distribution)$ ]]; then
|
|
echo "❌ Invalid category: $CATEGORY"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
# Check state
|
|
STATE=$(grep -oP "'state' => '\K[a-z]+(?=')" ext_emconf.php)
|
|
if [[ ! "$STATE" =~ ^(alpha|beta|stable|experimental|test|obsolete|excludeFromUpdates)$ ]]; then
|
|
echo "❌ Invalid state: $STATE"
|
|
((ERRORS++))
|
|
fi
|
|
|
|
# Check constraints
|
|
grep -A 5 "'depends' =>" ext_emconf.php | grep -q "'typo3'" || { echo "❌ Missing TYPO3 dependency"; ((ERRORS++)); }
|
|
grep -A 5 "'depends' =>" ext_emconf.php | grep -q "'php'" || { echo "❌ Missing PHP dependency"; ((ERRORS++)); }
|
|
|
|
# Check recommended author fields
|
|
grep -q "'author' =>" ext_emconf.php || { echo "⚠️ Missing author"; ((WARNINGS++)); }
|
|
grep "'author_email' =>" ext_emconf.php | grep -q "@" || { echo "⚠️ Missing or invalid author_email"; ((WARNINGS++)); }
|
|
grep -q "'author_company' =>" ext_emconf.php || { echo "⚠️ Missing author_company"; ((WARNINGS++)); }
|
|
|
|
echo ""
|
|
echo "Validation complete: $ERRORS errors, $WARNINGS warnings"
|
|
exit $ERRORS
|
|
```
|
|
|
|
---
|
|
|
|
## Common Violations and Fixes
|
|
|
|
### 1. Using declare(strict_types=1)
|
|
|
|
❌ **WRONG - TER upload FAILS:**
|
|
```php
|
|
<?php
|
|
declare(strict_types=1);
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'title' => 'My Extension',
|
|
];
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
<?php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'title' => 'My Extension',
|
|
];
|
|
```
|
|
|
|
### 2. Hardcoded Extension Key
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
$EM_CONF['my_extension'] = [
|
|
'title' => 'My Extension',
|
|
];
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
$EM_CONF[$_EXTKEY] = [
|
|
'title' => 'My Extension',
|
|
];
|
|
```
|
|
|
|
### 3. Invalid Category
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
'category' => 'utility', // Not a valid category
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
'category' => 'misc', // Use 'misc' for utilities
|
|
```
|
|
|
|
### 4. Invalid Version Format
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
'version' => 'v1.0.0', // No 'v' prefix
|
|
'version' => '1.0', // Must have 3 parts
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
'version' => '1.0.0',
|
|
```
|
|
|
|
### 5. Missing PHP/TYPO3 Constraints
|
|
|
|
❌ **WRONG:**
|
|
```php
|
|
'constraints' => [
|
|
'depends' => [
|
|
'extbase' => '12.4.0-12.4.99',
|
|
],
|
|
],
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
```php
|
|
'constraints' => [
|
|
'depends' => [
|
|
'typo3' => '12.4.0-13.4.99',
|
|
'php' => '8.1.0-8.4.99',
|
|
'extbase' => '12.4.0-12.4.99',
|
|
],
|
|
],
|
|
```
|
|
|
|
### 6. Mismatched composer.json Constraints
|
|
|
|
❌ **WRONG:**
|
|
|
|
composer.json:
|
|
```json
|
|
"require": {
|
|
"typo3/cms-core": "^13.4"
|
|
}
|
|
```
|
|
|
|
ext_emconf.php:
|
|
```php
|
|
'typo3' => '12.4.0-12.4.99', // Mismatch!
|
|
```
|
|
|
|
✅ **CORRECT:**
|
|
|
|
composer.json:
|
|
```json
|
|
"require": {
|
|
"typo3/cms-core": "^13.4"
|
|
}
|
|
```
|
|
|
|
ext_emconf.php:
|
|
```php
|
|
'typo3' => '13.4.0-13.4.99', // Matches!
|
|
```
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
### Critical Checks
|
|
```bash
|
|
# Will TER upload fail?
|
|
grep "declare(strict_types" ext_emconf.php && echo "❌ TER FAIL"
|
|
|
|
# Uses $_EXTKEY?
|
|
grep '\$EM_CONF\[$_EXTKEY\]' ext_emconf.php && echo "✅ OK"
|
|
|
|
# Valid category?
|
|
grep -oP "'category' => '\K[a-z]+(?=')" ext_emconf.php | grep -qE '^(be|module|fe|plugin|misc|services|templates|example|doc|distribution)$' && echo "✅ OK"
|
|
|
|
# Valid state?
|
|
grep -oP "'state' => '\K[a-z]+(?=')" ext_emconf.php | grep -qE '^(alpha|beta|stable|experimental|test|obsolete|excludeFromUpdates)$' && echo "✅ OK"
|
|
```
|