14 KiB
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
declare(strict_types=1);
$EM_CONF[$_EXTKEY] = [
// configuration
];
✅ CORRECT:
<?php
$EM_CONF[$_EXTKEY] = [
// configuration
];
Detection:
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:
$EM_CONF['my_extension'] = [
// configuration
];
✅ CORRECT:
$EM_CONF[$_EXTKEY] = [
// configuration
];
Detection:
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
function getVersion() { return '1.0.0'; }
$EM_CONF[$_EXTKEY] = [
'version' => getVersion(),
];
❌ WRONG:
<?php
$EM_CONF[$_EXTKEY] = [
'title' => 'My Extension',
];
// Additional initialization code
require_once 'setup.php';
✅ CORRECT:
<?php
$EM_CONF[$_EXTKEY] = [
'title' => 'My Extension',
'version' => '1.0.0',
];
Detection:
# 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:
'title' => 'My Extension',
Validation:
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:
'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:
'description' => '', // Empty
'description' => 'Extension', // Too vague
'description' => 'Some tools', // Meaningless
Validation:
# 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:
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:
'author' => 'Sebastian Koschel, Sebastian Mendel, Rico Sonntag',
Validation:
grep "'author' =>" ext_emconf.php && echo "✅ Has author" || echo "❌ Missing author"
author_email
Format: Email address(es), comma-separated for multiple
Example:
'author_email' => 'developer@company.com, other@company.com',
Validation:
grep "'author_email' =>" ext_emconf.php | grep -q "@" && echo "✅ Has author_email" || echo "❌ Missing author_email"
author_company
Format: Company name
Example:
'author_company' => 'Company Name GmbH',
Validation:
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:
'category' => 'fe',
Validation:
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:
'state' => 'stable',
Validation:
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
'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 rangephp- PHP version range
Example:
'depends' => [
'typo3' => '12.4.0-13.4.99',
'php' => '8.1.0-8.4.99',
'fluid' => '12.4.0-13.4.99',
],
Validation:
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:
'conflicts' => [
'old_extension' => '',
],
suggests
Purpose: Recommended companion extensions (loaded before current extension)
Example:
'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 only13.4.0-13.4.99- TYPO3 13 LTS only12.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' => '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
# 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 Englishdescription- Short, precise descriptionversion- 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 rangeconstraints.depends.php- PHP version range
Recommended (SHOULD have):
author- Developer name(s)author_email- Contact email(s)author_company- Company nameconstraints.conflicts- Conflicting extensions (even if empty array)constraints.suggests- Suggested companion extensions
Complete Example:
<?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
#!/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
declare(strict_types=1);
$EM_CONF[$_EXTKEY] = [
'title' => 'My Extension',
];
✅ CORRECT:
<?php
$EM_CONF[$_EXTKEY] = [
'title' => 'My Extension',
];
2. Hardcoded Extension Key
❌ WRONG:
$EM_CONF['my_extension'] = [
'title' => 'My Extension',
];
✅ CORRECT:
$EM_CONF[$_EXTKEY] = [
'title' => 'My Extension',
];
3. Invalid Category
❌ WRONG:
'category' => 'utility', // Not a valid category
✅ CORRECT:
'category' => 'misc', // Use 'misc' for utilities
4. Invalid Version Format
❌ WRONG:
'version' => 'v1.0.0', // No 'v' prefix
'version' => '1.0', // Must have 3 parts
✅ CORRECT:
'version' => '1.0.0',
5. Missing PHP/TYPO3 Constraints
❌ WRONG:
'constraints' => [
'depends' => [
'extbase' => '12.4.0-12.4.99',
],
],
✅ CORRECT:
'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:
"require": {
"typo3/cms-core": "^13.4"
}
ext_emconf.php:
'typo3' => '12.4.0-12.4.99', // Mismatch!
✅ CORRECT:
composer.json:
"require": {
"typo3/cms-core": "^13.4"
}
ext_emconf.php:
'typo3' => '13.4.0-13.4.99', // Matches!
Quick Reference
Critical Checks
# 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"