Files
gh-netresearch-claude-code-…/references/ext-emconf-validation.md
2025-11-30 08:43:22 +08:00

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 range
  • php - 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 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' => '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 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
$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"