helmich/typo3-typoscript-parser
Installation:
composer require helmich/typo3-typoscript-parser
Ensure your project uses PHP 8.1+ (required since v2.6.0).
First Use Case:
Parse a TypoScript file (typoscript.ts) into an Abstract Syntax Tree (AST):
use Helmich\TypoScriptParser\Parser\Parser;
use Helmich\TypoScriptParser\Tokenizer\Tokenizer;
$typoscript = file_get_contents('path/to/typoscript.ts');
$parser = new Parser(new Tokenizer());
$statements = $parser->parse($typoscript);
Key Classes to Know:
Parser: Converts TypoScript to AST.Tokenizer: Splits raw TypoScript into tokens.PrettyPrinter: Converts AST back to TypoScript.Traverser + Visitor: Analyze/modify AST (e.g., linting, transformations).$parser = new Parser(new Tokenizer());
$statements = $parser->parse(file_get_contents('Config.ts'));
$traverser = new Traverser($statements);
$traverser->addVisitor(new MyCustomVisitor());
$traverser->walk();
Example Visitor:
class MyCustomVisitor implements Visitor {
public function enterNode(Statement $node) {
if ($node instanceof Assignment) {
// Modify or log assignments
}
}
}
$printer = new PrettyPrinter();
$printer->printStatements($modifiedStatements, new StreamOutput(fopen('output.ts', 'w')));
$config = PrettyPrinterConfiguration::create()
->withSpaceIndentation(4)
->withConditionTermination(PrettyPrinterConditionTermination::EnforceEnd);
$printer = new PrettyPrinter($config);
AppServiceProvider:
$this->app->singleton(Parser::class, function ($app) {
return new Parser(new Tokenizer());
});
use Illuminate\Console\Command;
class TypoScriptLintCommand extends Command {
protected $signature = 'typo3:lint {file}';
public function handle() {
$statements = app(Parser::class)->parse(file_get_contents($this->argument('file')));
// Traverse and validate
}
}
try {
$statements = $parser->parse($typoscript);
} catch (ParseError $e) {
$this->error("TypoScript error: " . $e->getMessage());
}
StatementDumper to inspect the tree:
$dumper = new StatementDumper();
echo $dumper->dump($statements);
PHP Version Compatibility:
Tokenization Quirks:
StatementDumper to debug.= .), but may cause unexpected behavior in older TYPO3 versions.PrettyPrinter Pitfalls:
withSpaceIndentation(4) for readability.withIndentConditions(), nested conditions may collapse.withClosingGlobalStatement() is set to avoid missing ] in output.Visitor Traversal:
Dump Tokens:
Extend Tokenizer to log tokens during development:
$tokenizer = new Tokenizer();
$tokenizer->setLogger(function ($token) {
error_log("Token: " . print_r($token, true));
});
AST Validation:
Compare parsed AST against expected structure using StatementDumper:
$dumper = new StatementDumper();
$this->assertStringContainsString('page = PAGE', $dumper->dump($statements));
Performance:
Custom Token Types:
Extend Tokenizer to handle non-standard TypoScript syntax:
class CustomTokenizer extends Tokenizer {
protected function getTokenRegex(): string {
return parent::getTokenRegex() . '|/\*custom\*/';
}
}
Visitor Patterns:
PrettyPrinter Extensions:
Override PrettyPrinter to customize output (e.g., add TYPO3 version headers):
class CustomPrinter extends PrettyPrinter {
public function printStatements(array $statements, OutputInterface $output) {
$output->writeln('# TYPO3 v12 Configuration');
parent::printStatements($statements, $output);
}
}
Tokenizer Options: Configure preprocessing (e.g., trim whitespace):
$tokenizer = new Tokenizer();
$tokenizer->setPreprocessCallback(function ($code) {
return preg_replace('/\s+/', ' ', $code); // Normalize whitespace
});
PrettyPrinter Flags:
withConditionTermination(EnforceEnd): Ensures conditions end with }.withIndentConditions(): Adds indentation for nested conditions.Symfony Integration:
If using Symfony DI, leverage the parser service directly:
# config/services.yaml
services:
Helmich\TypoScriptParser\Parser\Parser:
arguments:
$tokenizer: '@Helmich\TypoScriptParser\Tokenizer\Tokenizer'
How can I help you explore Laravel packages today?