twigphp/Twig
67.3
Adequate · 26 September 2026
24.5k
lines of production code
PHP
primary language
4
measurements over time
What this system is
This system is the Twig template engine, a PHP library for rendering templates with a focus on performance, security, and developer ergonomics. It provides a comprehensive suite of extensions for handling HTML, CSS, Markdown, internationalization, and caching, alongside a Symfony bundle for seamless integration. The core engine features a modernized expression parser, generator-based rendering for reduced memory usage, and robust sandboxing capabilities to safely execute untrusted code.
How it got here
2009–2019 — Twig 3.30 major release and ecosystem expansion
57 changes.
This period covers the development and release of Twig 3.30, featuring a comprehensive rewrite of the compilation engine to use PHP generators for improved performance, alongside a new attribute-based API for registering extensions. It also introduced a structured caching layer, enhanced error reporting, and stricter sandbox security policies. Concurrently, the project expanded its ecosystem with new extra packages for HTML, Markdown, internationalization, and CSS inlining, supported by a new Symfony bundle for simplified integration.
2021–2024 — Twig 4.0 preparation and extra extensions
35 changes.
This period focused on preparing the codebase for Twig 4.0 by refactoring internal AST nodes, extracting escaping logic into dedicated runtime classes, and deprecating legacy internal functions. It also introduced new features such as the cache tag, enum handling, and sandboxed rendering, while significantly expanding test coverage across the Twig Extra Bundle and its various extension packages.
2025–2026 — Expression parser refactoring and sandbox security
9 changes.
The project restructured the expression parser into a modular architecture supporting distinct prefix and infix operators, enabling advanced syntax features like destructuring and arrow functions. Concurrently, comprehensive test coverage was added to validate the new parsing logic and enforce strict security policies within the Twig sandbox environment.
Features
Add Inky email template support via new \`inky\_to\_html\` filter
The \extra/inky-extra\ package now includes the \InkyExtension\, which registers the \inky\_to\_html\ Twig filter. This filter processes Inky email templates (from Zurb) by converting them to HTML using the Pinky library. The extension is configured with \pre\_escape\ set to \html\ to ensure safe handling of input, and the package includes standard configuration files for testing and distribution.
extra/inky-extra · high confidence
Add Intl Twig extension for locale-aware formatting
The new \IntlExtension\ provides filters for formatting dates, times, numbers, and lists according to locale settings, including support for PHP 8.0+ relative date formats and PHP 8.5's \IntlListFormatter\. It also includes filters for resolving human-readable names for countries, currencies, languages, and timezones, while caching formatters to optimize performance.
extra/intl-extra · high confidence
Add Twig String Extension for Unicode and Inflection
This change introduces the new \extra/string-extra\ package, a Twig extension that integrates the Symfony String component. It provides four new Twig filters: \u\ to wrap text in a \UnicodeString\, \slug\ to generate slugs using \AsciiSlugger\, and \singular\/\plural\ to handle word inflection. The inflection filters support English, French, and Spanish locales, allowing users to easily manipulate text casing and plurality directly in their templates.
extra/string-extra · high confidence
Add script to generate operator precedence documentation
A new PHP script, bin/generate\_operators\_precedence.php, has been added to automatically generate the operator precedence table in the documentation (doc/operators\_precedence.rst). This script iterates through registered expression parsers to produce a formatted RST table showing precedence, operator names, types, associativity, and descriptions, including a separate section for Twig 4.0 with adjusted precedences indicated by arrows.
bin · high confidence
Compiler passes for Twig extension suggestions and cache pool compatibility
Added two new dependency injection compiler passes to improve Twig integration. MissingExtensionSuggestorPass registers callbacks to suggest missing filters, functions, and tags in debug mode, with conditional logic to maintain compatibility with older Symfony versions that lack the getAutoconfiguredAttributes method. TwigCachePoolPass prevents performance issues by removing the Twig cache decorator when the underlying cache pool is already tag-aware, ensuring efficient cache reads.
extra/twig-extra-bundle/DependencyInjection/Compiler · high confidence
Configurable CommonMark support in Twig Extra Bundle
The Twig Extra Bundle now allows users to configure the CommonMark Markdown renderer via the \twig\_extra.commonmark\ configuration key. This includes options for HTML input handling, nesting levels, and CommonMark core settings (such as emphasis/strong syntax). The bundle conditionally loads the League CommonMark integration when the \markdown\ extension is enabled and the library is present, passing the user's configuration to the converter factory.
extra/twig-extra-bundle/DependencyInjection · high confidence
Initial project scaffolding and tooling configuration
This change establishes the foundational configuration for the project by adding essential development and quality-assurance files. It introduces an \.editorconfig\ to standardize indentation and line endings across PHP, test, and documentation files, alongside \.gitattributes\ and \.gitignore\ to manage repository exports and local artifacts. Furthermore, it adds a \.php-cs-fixer.dist.php\ configuration file that enforces the Symfony coding standard with specific customizations for void return types, and a \CHANGELOG\ file to document version history starting from 3.30.1.
(repo-wide) · high confidence
Initial release of Twig Extra Bundle
This change introduces the Twig Extra Bundle, a Symfony bundle that automatically registers all Twig extra extensions (cache, HTML, Markdown, Intl, CSS inliner, Inky, and string) without requiring manual configuration. It includes a central registry (Extensions.php) to map filters, functions, and tags to their respective packages, and a MissingExtensionSuggestor that provides helpful error messages when a user attempts to use an extension that is not installed. The bundle also sets up the necessary Symfony compiler passes to handle cache pool tagging and integrates with the League CommonMark converter factory for Markdown support.
extra/twig-extra-bundle · high confidence
Introduce RuntimeLoader interface and implementations
Added the Twig\\RuntimeLoader\\RuntimeLoaderInterface along with two concrete implementations: ContainerRuntimeLoader, which resolves runtime services from a PSR-11 container, and FactoryRuntimeLoader, which uses a map of class names to factory callables. This provides a standardized way to lazily load runtime implementations for Twig elements (filters, functions, tests) via dependency injection or custom factories.
src/RuntimeLoader · high confidence
Introduce Twig Cache Extra for template fragment caching
This change adds the \extra/cache-extra\ package, which provides a Twig extension integrating with the Symfony Cache component. It introduces a \cache\ tag that allows users to cache specific template fragments, leveraging the \CacheExtension\ and \CacheRuntime\ classes to manage caching logic. The package includes standard configuration files such as \.gitignore\ and \.gitattributes\ to manage version control artifacts, along with PHPUnit configuration for testing.
extra/cache-extra · high confidence
Introduce the \`{% cache %}\` template tag for caching rendered content
The \extra/cache-extra\ extension now provides a new \{% cache %}\ tag that allows templates to cache their rendered output. Users can specify a unique cache key and optionally configure a time-to-live (TTL) and tags for invalidation. The tag parses the block body, wraps it in a \CacheNode\, and outputs the result using a \RawFilter\ to prevent double-escaping.
extra/cache-extra/TokenParser · high confidence
Introduces ProfilerNodeVisitor for template, block, and macro profiling
The new ProfilerNodeVisitor class now instruments the Twig compilation process to track performance metrics for templates, blocks, and macros. When visiting Module, Block, or Macro nodes, it wraps the relevant code sections with EnterProfileNode and LeaveProfileNode markers, enabling the profiler to capture execution data for these specific units. The visitor uses a hash-based variable name (xxh128 on PHP 8.1+) to ensure unique internal identifiers for each extension being profiled.
src/Profiler/NodeVisitor · high confidence
New CacheNode implementation for template caching
The CacheNode class has been introduced to handle the compilation of cache tags, enabling templates to define cached content with configurable keys, time-to-live (TTL) expiration, and cache tags. This node wraps the template body in a CaptureNode to collect output, then compiles code that interacts with the PSR-6 compatible cache runtime to store and retrieve the rendered content based on the provided key, while optionally applying tags and expiration settings.
extra/cache-extra/Node · high confidence
New HTML helper functions and CVA class in Twig HTML extension
The Twig HTML extension now includes a \Cva\ class and corresponding \html\_cva\ function to manage CSS class variants (base classes, variants, compound variants, and defaults). It also adds an \html\_attr\ function for easier HTML attribute output, supporting \Twig\\Markup\ and rendering backed enums by their backing value. Existing functions like \html\_classes\ and \html\_attr\_merge\ are present, along with filters like \data\_uri\, \html\_attr\_merge\, and \html\_attr\_type\.
extra/html-extra · high confidence
New PHP attributes and extension base class for simplified extension development
Twig now provides an \AbstractExtension\ base class that implements \LastModifiedExtensionInterface\ to automatically track extension modification times for cache invalidation, and introduces \AttributeExtension\ to allow developers to define filters, functions, and tests using PHP 8 attributes (\AsTwigFilter\, \AsTwigFunction\, \AsTwigTest\) instead of manual registration. This change also refactors existing extensions like \CoreExtension\, \EscaperExtension\, and \DebugExtension\ to extend this new base class, standardizing how extensions report their metadata and simplifying the creation of new extensions.
src/Extension · high confidence
New Profile class with secure serialization and timing accessors
The Profiler now includes a new Profile class that implements Serializable and provides explicit accessors for start time, end time, duration, and memory usage. A key behavioral change is the serialization mechanism: Profile::unserialize() now restricts allowed classes to only the Profile class itself, preventing arbitrary object instantiation during unserialization. The class also introduces constants for profile types (ROOT, BLOCK, TEMPLATE, MACRO) and uses constructor property promotion for template, type, and name.
src/Profiler · high confidence
New Twig CssInliner extension with XSS-safe HTML filtering
The \extra/cssinliner-extra\ package introduces a new Twig extension providing the \inline\_css\ filter, which inlines CSS styles into HTML documents using the \tijsverkoyen/css-to-inline-styles\ library. To prevent cross-site scripting (XSS) vulnerabilities, the filter is configured with \pre\_escape\ set to \html\, ensuring that HTML input is properly escaped before processing. The package also includes standard configuration files for PHPUnit testing and distribution packaging.
extra/cssinliner-extra · high confidence
New Twig Markdown Extension for converting Markdown and HTML
The \extra/markdown-extra\ package introduces a new Twig extension providing two filters: \markdown\_to\_html\ to convert Markdown content to HTML, and \html\_to\_markdown\ to convert HTML back to Markdown. The \markdown\_to\_html\ filter automatically detects and uses the best available Markdown library from your dependencies (League CommonMark, Michelf MarkdownExtra, Parsedown, or Tempest Markdown) to perform the conversion, while the \html\_to\_markdown\ filter relies on the \league/html-to-markdown\ package. This allows users to easily integrate bidirectional content conversion directly within their Twig templates.
extra/markdown-extra · high confidence
New cache abstraction and implementations for template caching
The src/Cache directory now provides a structured caching layer for Twig templates, introducing a new CacheInterface that defines methods for generating keys, writing, loading, and retrieving timestamps for cached template classes. This includes several concrete implementations: FilesystemCache for standard disk-based storage with optional bytecode invalidation support, ReadOnlyFilesystemCache for read-only filesystem scenarios, ChainCache to aggregate multiple cache adapters for fallback or multi-store strategies, and NullCache for disabling caching entirely. Additionally, a RemovableCacheInterface is introduced to allow explicit removal of specific cached template classes, enhancing cache management capabilities.
src/Cache · high confidence
New enum and sandboxed rendering functions
Added the \enum\ and \enum\_cases\ functions to allow retrieving enum cases and specific enum values by name in templates, and introduced the \render\_sandboxed\ function to enable rendering templates within a sandboxed environment with a specified output strategy.
src/Node/Expression/FunctionNode · high confidence
New template loaders: ArrayLoader, ChainLoader, and FilesystemLoader
The src/Loader directory now includes three new loader implementations: ArrayLoader, which allows loading templates from a PHP array (primarily for unit testing); ChainLoader, which aggregates multiple loaders to search for templates across different sources; and FilesystemLoader, which loads templates from the filesystem with support for namespace-based path organization. These classes implement the new LoaderInterface, providing a unified API for template retrieval, caching, and freshness checks.
src/Loader · high confidence
New utility classes for callable argument extraction and deprecation collection
Added several new internal utility classes in the \src/Util\ namespace to support improved callable handling and tooling. \CallableArgumentsExtractor\ and \CallableParameters\ provide robust reflection and argument mapping for Twig filters, functions, and tests, enabling better validation of required arguments and support for named/camel-case arguments. \ReflectionCallable\ extracts and normalizes PHP callable metadata from Twig callable interfaces. \DeprecationCollector\ allows scanning template directories to collect deprecation warnings during parsing, aiding in template maintenance. \TemplateDirIterator\ supports directory iteration for template content retrieval. These changes enhance the internal infrastructure for argument processing and deprecation tracking without altering public API behavior.
src/Util · high confidence
Twig 3.30 introduces attribute-based extension registration and yield-ready rendering
This release adds new PHP attributes (\#\[AsTwigFilter\], \#\[AsTwigFunction\], \#\[AsTwigTest\]) to simplify registering template filters, functions, and tests, alongside a \#\[YieldReady\] attribute to mark nodes as ready for the new yield-based rendering mode. It also introduces a \#\[FirstClassTwigCallableReady\] attribute for nodes accepting TwigCallable instances, a new AbstractTwigCallable base class with unified deprecation handling via DeprecatedCallableInfo, and a BlockChain class for composing blocks across templates. The Environment now supports a use\_yield option to enforce yield-based output, and the ExpressionParser is deprecated in favor of the new ExpressionParsers system.
src · high confidence
Architecture
Refactored expression parsing into modular prefix parsers
The expression parser has been restructured to use dedicated, pluggable classes for handling prefix expressions, replacing the previous monolithic logic. This change introduces specific parsers for grouping (parentheses), literals (booleans, nulls, numbers, strings, arrays, and mappings), and unary operators, each implementing a standard interface. This modularization allows for clearer separation of concerns and easier extension of the parser's capabilities, such as adding new operator types or modifying precedence rules, without altering the core parsing engine.
src/ExpressionParser/Prefix · high confidence
Behavioural changes
AST nodes refactored for generator-based output and enhanced sandbox security
The template compilation engine has been rewritten to use PHP generators (yield) instead of output buffering, significantly reducing memory usage and improving performance for large templates. This change introduces a new \\#\[YieldReady\]\ attribute to mark nodes as compatible with the new streaming output model. Additionally, sandbox security checks have been hardened to prevent bypasses via template inclusion and \\_\_toString\ coercion, and the \For\ loop now supports an \else\ block that executes when the sequence is empty.
src/Node · high confidence
Dedicated Sandbox class and stricter security policy enforcement
The sandbox is now a first-class citizen with a dedicated \Twig\\Sandbox\\Sandbox\ class that requires a dedicated, freshly built environment and a strict security policy, ensuring untrusted templates are always rendered in a fully sandboxed context. The \SecurityPolicy\ now includes a strict mode that deprecates the historical implicit allowance of \extends\/\use\ tags and \parent\/\block\/\attribute\ functions, requiring them to be explicitly whitelisted to prepare for Twig 4.0 behavior. Additionally, the sandbox now supports selective enabling based on a template's source via the (now deprecated) \SourcePolicyInterface\, and the security checker enforces stricter checks on method and property access, including proper handling of spread operands and traversable objects.
src/Sandbox · high confidence
Deprecate internal twig\_inline\_css function
The internal \twig\_inline\_css\ function in \extra/cssinliner-extra/Resources/functions.php\ is now deprecated as of Twig 3.9.0. Calling this function will trigger a deprecation warning, guiding users to rely on the underlying \CssInlinerExtension::inlineCss\ method instead.
extra/cssinliner-extra/Resources · high confidence
Deprecation of internal Twig functions in src/Resources
The internal helper functions located in src/Resources (such as twig\_escape\_filter, twig\_var\_dump, and twig\_template\_from\_string) are now deprecated as of Twig 3.9. These functions now trigger deprecation warnings and delegate to their respective extension classes or runtimes, signaling that direct usage of these internal APIs is no longer supported and users should rely on the public extension interfaces instead.
src/Resources · high confidence
Deprecation of the internal twig\_inky function
The internal \twig\_inky\ function in \extra/inky-extra/Resources/functions.php\ is now deprecated as of Twig 3.9.0. Calling this function will trigger a deprecation warning, signaling that it is an internal implementation detail and should not be used directly by applications.
extra/inky-extra/Resources · high confidence
Deprecation of twig\_html\_classes function in Twig 3.9.0
The internal \twig\_html\_classes\ function in \extra/html-extra/Resources/functions.php\ is now deprecated as of Twig 3.9.0. While the function remains available and continues to delegate to \HtmlExtension::htmlClasses\, its use will trigger a deprecation warning. Users should migrate to using the \HtmlExtension\ directly to avoid future removal of this internal API.
extra/html-extra/Resources · high confidence
Escaping logic extracted to dedicated runtime classes
The escaping logic has been moved from the extension into new runtime classes (\EscaperRuntime\ and \SandboxBridgeRuntime\) that implement \RuntimeExtensionInterface\. This change introduces a new \html\_attr\_relaxed\ escaping strategy, allows registering custom escapers and safe classes via the runtime, and ensures that \Stringable\ objects are handled correctly during auto-escaping. Users relying on the previous internal implementation details may need to adjust how they interact with the escaper, but the public API for escaping templates remains consistent.
src/Runtime · high confidence
Improved error reporting with column numbers and syntax suggestions
The error handling classes in src/Error have been updated to provide more precise debugging information. The base Error class now supports tracking and displaying the specific column number where an error occurs, enhancing the detail of error messages. Additionally, the SyntaxError class introduces an addSuggestions method that automatically appends likely corrections to the error message when a syntax error is detected, helping developers fix issues faster.
src/Error · high confidence
New html\_attr function and value objects for safer HTML attribute handling
The \html\_attr\ function is introduced to simplify outputting HTML attributes, featuring new classes like \InlineStyle\ and \SeparatedTokenList\ that implement \AttributeValueInterface\ and \MergeableInterface\ for robust merging and conversion logic. This update also fixes a bug where \InlineStyle\ incorrectly dropped style declarations with a value of zero, ensuring that valid CSS properties like \width: 0\ are now correctly rendered in the output.
extra/html-extra/HtmlAttr · high confidence
Node visitors refactored with new correctness checks and deprecation warnings
The node visitor system has been restructured to improve template validation and prepare for future versions. A new CorrectnessNodeVisitor now validates template semantics, specifically checking for invalid nesting of block definitions and issuing deprecation warnings when macros are called without parentheses. The EscaperNodeVisitor has been simplified to handle escaping logic more efficiently, while the OptimizerNodeVisitor now explicitly deprecates the OPTIMIZE\_RAW\_FILTER and OPTIMIZE\_TEXT\_NODES modes. Additionally, the AbstractNodeVisitor class is deprecated in favor of direct implementation of the NodeVisitorInterface, and the SandboxNodeVisitor has been updated to enforce stricter string coercion checks for arguments passed to filters and functions.
src/NodeVisitor · high confidence
Redesigned expression parser with infix operator support
The expression parser has been refactored to use a new infix-based architecture, moving operators into dedicated parsers within the \src/ExpressionParser/Infix\ directory. This change introduces support for new syntax features including arrow functions (\x =\> expr\), object and sequence destructuring assignments (e.g., \\[a, b\] = $array\), and null-safe attribute access (\?.\). It also enforces stricter argument parsing for filters, functions, and macros, requiring parentheses for macro calls and preventing normal arguments from following unpacked arguments. Additionally, the \defined\ test for macros no longer accepts parentheses, and the precedence for the filter operator (\\|\) has been adjusted.
src/ExpressionParser/Infix · high confidence
Redesigned token parser architecture with new tags and sandbox deprecation
The token parser system has been restructured around a new \AbstractTokenParser\ base class and a \TokenParserInterface\ that now requires the \setParser\ method. This change introduces several new template tags: \apply\ (to apply filters to a block of content), \guard\ (to conditionally render content based on the existence of functions, filters, or tests), \types\ (to declare variable types for static analysis), and \deprecated\ (to emit deprecation notices from templates). Existing tags have been updated to use these new internal structures, notably the \for\ tag which now supports an \else\ block for empty sequences. Additionally, the \sandbox\ tag is now deprecated in favor of more granular sandboxing controls, and the \isAlwaysAllowedInSandbox\ method on token parsers is deprecated, signaling a shift in how sandbox permissions are managed.
src/TokenParser · high confidence
Refactored Profiler Dumpers to use a shared BaseDumper and added HTML escaping
The profiler dumpers (HtmlDumper, TextDumper, BlackfireDumper) have been refactored to extend a new abstract BaseDumper class, which centralizes the profile traversal and formatting logic. This change introduces HTML escaping for template and profile names in the HtmlDumper to prevent potential XSS issues in the rendered profiler output, and ensures consistent formatting across text and HTML profiles.
src/Profiler/Dumper · high confidence
Refactored binary operators into a dedicated class hierarchy
All binary operators (such as addition, comparison, and logical operators) have been restructured into individual classes under the \Twig\\Node\\Expression\\Binary\ namespace, extending a new \AbstractBinary\ base class. This change introduces stricter type enforcement, requiring that constructor arguments be instances of \AbstractExpression\ (triggering deprecations in version 3.15 for non-conforming nodes) and implements the \BinaryInterface\ for consistent operation handling. The refactoring also adds compile-time validation for the \matches\ operator's regular expressions and ensures that boolean operators like \and\, \or\, and \xor\ explicitly wrap their operands in truthiness tests before compilation.
src/Node/Expression/Binary · high confidence
Refactored default, escape, and raw filters into dedicated node classes
The default, escape, and raw filters are now implemented as specific node classes (DefaultFilter, EscapeFilter, RawFilter) extending FilterExpression, replacing previous inline or generic handling. This change introduces a deprecation warning when the 'node' argument passed to these filters is not an AbstractExpression instance, enforcing stricter type expectations for internal filter logic. Additionally, the escape filter now supports a 'template\_escaper' attribute to optimize compilation by directly calling the fetched escaper runtime, while the default filter's logic for handling undefined variables has been moved into this dedicated class structure.
src/Node/Expression/Filter · high confidence
Refactored expression node hierarchy and argument handling
The expression node classes have been restructured to improve type safety and performance. A new AbstractExpression base class now provides shared functionality for generator detection and explicit parentheses tracking. CallExpression has been redesigned to use a dedicated CallableArgumentsExtractor for handling named arguments, variadics, and special parameters like environment or context, replacing the previous inline logic. Several node classes (such as NameExpression, AssignNameExpression, and MethodCallExpression) have been deprecated in favor of more specific alternatives like ContextVariable and MacroReferenceExpression. Additionally, the codebase now enforces stricter type requirements for constructor arguments, triggering deprecations when non-AbstractExpression nodes are passed where expressions are expected.
src/Node/Expression · high confidence
Refactored expression parser architecture with new interfaces and precedence handling
The expression parser system has been restructured to support distinct prefix and infix operators, introducing new interfaces (PrefixExpressionParserInterface, InfixExpressionParserInterface) and an ExpressionParsers registry that manages operator tokens and precedence changes. This change adds explicit support for associativity (Left/Right) via InfixAssociativity and allows parsers to declare precedence shifts via PrecedenceChange, enabling more accurate and flexible expression parsing behavior for users.
src/ExpressionParser · high confidence
Refactored macro and variable handling with new AST node classes
The internal representation of variables and macros has been restructured to improve clarity and inheritance logic. New AST node classes have been introduced: \AssignMacroVariable\ and \MacroVariable\ now handle macro-specific logic, replacing the previous generic \AssignNameExpression\ and \NameExpression\ patterns for macros. \AssignContextVariable\ and \ContextVariable\ are now distinct from \AssignNameExpression\ and \NameExpression\, allowing for more precise \instanceof\ checks and inheritance handling. Additionally, \AssignTemplateVariable\ and \TemplateVariable\ are deprecated in favor of their macro-specific counterparts (\AssignMacroVariable\ and \MacroVariable\), signaling a shift towards explicit macro variable management in the compiled template code.
src/Node/Expression/Variable · high confidence
Refactored profiler node classes to use modern PHP practices
The profiler node classes (EnterProfileNode and LeaveProfileNode) have been rewritten to use the Twig\\Profiler\\Node namespace, include strict type hints on constructors and methods, and implement the \#\[YieldReady\] attribute. This change improves code clarity and compatibility with modern PHP standards without altering the profiling behavior itself.
src/Profiler/Node · high confidence
Refactored unary expression handling with explicit parentheses support
Unary expressions (negation, positive, spread, string cast, and logical not) have been restructured into a dedicated namespace with a new AbstractUnary base class. This change introduces support for detecting and preserving explicit parentheses in compiled output, ensuring that expressions like \-(x)\ are rendered correctly rather than losing their grouping. Additionally, the \NotUnary\ implementation now wraps its operand in a \TrueTest\ to standardize boolean evaluation, and the base class now emits a deprecation warning if subclasses are instantiated with non-AbstractExpression nodes.
src/Node/Expression/Unary · high confidence
Switch documentation build process to Symfony Docs Builder
The documentation build script in doc/\_build has been replaced with a new PHP-based tool using Symfony Docs Builder. This change updates the underlying engine for generating the documentation site, replacing the previous method (likely Sphinx-based) with a dedicated builder that handles content processing, image handling, and output generation. Users building the docs locally or in CI will now use this new script, which includes specific logic to fix asset URLs for subdirectory deployment and provides detailed error reporting if the build fails.
_doc/\build · high confidence
Fixes
New DI service definitions for Twig extra extensions
The bundle now includes explicit Dependency Injection configuration files for its various Twig extensions (cache, CSS inliner, HTML, Inky, Intl, Markdown, String, and the missing-extension suggestor). This ensures that services like \CacheExtension\, \CssInlinerExtension\, \HtmlExtension\, \InkyExtension\, \IntlExtension\, \MarkdownExtension\, \StringExtension\, and \MissingExtensionSuggestor\ are correctly registered and tagged, resolving previous issues with service discovery and compatibility with older Symfony versions.
extra/twig-extra-bundle/Resources · high confidence
Test coverage
Added comprehensive test coverage for Twig core components; Added exception fixture tests for Twig template errors; Added functional and integration tests for the CSS inliner extension; Added functional and integration tests for the Cache extension; Added integration test fixtures for Twig Extra Bundle; Added integration tests for the String extension; Added legacy tests for the deprecated sandbox tag; Added regression tests for Twig template engine edge cases; Added test coverage for new HTML-extra utilities; Added test fixtures for Twig functions; Added test fixtures for autoescape, include, and verbatim tags; Added test fixtures for cache tag functionality; Added test fixtures for for and set tags; Added test fixtures for intl-extra Twig filters and functions; Added test fixtures for macro argument handling and syntax rules; Added test fixtures for macro tag behavior and validation; Added test fixtures for string filters; Added test fixtures for template inheritance and block behavior; Added test fixtures for the Twig guard tag; Added test fixtures for the embed tag; Added test fixtures for the include() function; Added test fixtures for the inline\_css filter; Added tests for Cache implementations; Added tests for ContextVariable and AssignContextVariable nodes; Added tests for EscaperRuntime escaping strategies; Added tests for Inky extra integration and security pre-escaping; Added tests for IntlExtension formatting and prototype behavior; Added tests for NodeVisitor components; Added tests for Profiler Dumpers; Added tests for TokenParser block, guard, and types features; Added tests for Twig cache pool decoration and extension configuration; Added tests for Twig template loaders; Added tests for legacy core sandbox security enforcement; Added tests for new HTML helper functions and filters; Added tests for operator precedence changes in Twig 4.0; Added tests for the Twig Sandbox security policy; Added tests for the apply tag behavior; Added tests for the enum Twig function; Added tests for the extra extension catalog and Markdown integration; Added tests for the include\_only function; Added tests for the markdown-extra Twig extension; Added tests for the new Attribute-based Extension API and Sandbox Bridge; Added tests for whitespace trimming behavior; Added tests to ensure test case classes are compatible with PHPUnit 11; Added unit tests for Escape and Raw filters; Added unit tests for Twig Node Expression classes; Added unit tests for Twig Node compilation; Added unit tests for binary expression nodes; Added unit tests for the Profiler Profile class; Comprehensive test coverage for the new expression language; Expanded test coverage for Twig tests and operators; Expanded test coverage for core Twig filters; New test node implementations for Twig expression tests; Updated test infrastructure for PHPUnit 11 compatibility.
Dependencies
Twig 3.21+ dependency requirements and PHP 8.1 minimum
The core Twig library and all extra packages (cache, cssinliner, html, inky, intl, markdown, string, and the extra-bundle) now require PHP 8.1 or higher and Twig 3.13 or 4.0 (with the core library itself requiring ^3.21\|^4.0). This update also aligns Symfony dependencies to versions 5.4, 6.4, 7.0, and 8.0 where applicable, and updates dev dependencies like phpunit-bridge and phpstan to their latest stable ranges.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 48 → 67 (+19.3)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 88 → 85 (-3.7)
- Architecture 94 → 99 (+5.0)
- Maturity 45 → 44 (-1.3)
- Readiness 32 → 89 (+56.9)
- Security 70 → 95 (+25.0)
Resolved (33)
- Coverage not measured — test suite did not build
- Dimension evaluation failed
- Duplicated block (10 lines × 2) (src/Node/SetNode.php)
- Duplicated block (12 lines × 2) (src/Lexer.php)
- Duplicated block (12 lines × 2) (src/Runtime/EscaperRuntime.php)
- Duplicated block (18 lines × 2) (extra/html-extra/Tests/CvaTest.php)
- Duplicated block (19 lines × 2) (extra/html-extra/Tests/CvaTest.php)
- Duplicated block (20 lines × 3) (extra/html-extra/Tests/CvaTest.php)
- Duplicated block (20 lines × 5) (extra/html-extra/Tests/CvaTest.php)
- Duplicated block (21 lines × 2) (extra/html-extra/Tests/CvaTest.php)
- Duplicated block (21 lines × 2) (extra/html-extra/Tests/CvaTest.php)
- Duplicated block (5 lines × 2) (src/Extension/CoreExtension.php)
- Duplicated block (5 lines × 2) (src/Node/Expression/CallExpression.php)
- Duplicated block (5 lines × 2) (src/Parser.php)
- Duplicated block (6 lines × 3) (src/Extension/AttributeExtension.php)
- Duplicated block (7 lines × 2) (src/Runtime/EscaperRuntime.php)
- Duplicated block (7 lines × 2) (src/Test/IntegrationTestCase.php)
- Duplicated block (9 lines × 2) (src/Extension/AttributeExtension.php)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 13 more
New (193)
- ArgumentsTrait.parseNamedArguments (cognitive 18) (src/ExpressionParser/Infix/ArgumentsTrait.php)
- AssignmentExpressionParser.parse (cognitive 17) (src/ExpressionParser/Infix/AssignmentExpressionParser.php)
- AttributeExtension.initFromAttributes (cognitive 16) (src/Extension/AttributeExtension.php)
- CallExpression.compileArguments (cognitive 25) (src/Node/Expression/CallExpression.php)
- CallExpression.compileArguments (cyclomatic 18) (src/Node/Expression/CallExpression.php)
- CallExpression.compileCallable (cognitive 17) (src/Node/Expression/CallExpression.php)
- CallExpression.getArguments (cognitive 55) (src/Node/Expression/CallExpression.php)
- CallExpression.getArguments (cyclomatic 32) (src/Node/Expression/CallExpression.php)
- CallExpression.getTwigCallable (cognitive 23) (src/Node/Expression/CallExpression.php)
- CallExpression.getTwigCallable (cyclomatic 26) (src/Node/Expression/CallExpression.php)
- CallableArgumentsExtractor.extractArguments (cognitive 60) (src/Util/CallableArgumentsExtractor.php)
- CallableArgumentsExtractor.extractArguments (cyclomatic 34) (src/Util/CallableArgumentsExtractor.php)
- CallableParameters.isStringCoercionSafe (cognitive 24) (src/Util/CallableParameters.php)
- CallableParameters.isStringCoercionSafe (cyclomatic 19) (src/Util/CallableParameters.php)
- Change coupling: ExpressionParser.php ↔ SafeAnalysisNodeVisitor.php (src/ExpressionParser.php)
- Change coupling: TwigFilter.php ↔ TwigFunction.php (src/TwigFilter.php)
- ClassTooLong: CoreExtension (src/Extension/CoreExtension.php)
- CoreExtension.compare (cognitive 24) (src/Extension/CoreExtension.php)
- CoreExtension.compare (cyclomatic 17) (src/Extension/CoreExtension.php)
- CoreExtension.convertDate (cognitive 21) (src/Extension/CoreExtension.php)
- …and 173 more
Changes since last survey
- 128 commits — 81 feature/other, 47 fixes
By area
- (repo) — 52 commits
- (root) — 32 commits
- src/Node — 6 commits
- doc/functions — 3 commits
- extra/intl-extra — 3 commits
- extra/twig-extra-bundle — 3 commits
- tests/Fixtures — 3 commits
- tests/Node — 3 commits
- doc/filters — 2 commits
- doc/templates.rst — 2 commits
- extra/html-extra — 2 commits
- src/BlockChain.php — 2 commits
- src/MacroNamespace.php — 2 commits
- tests/ExpressionParserTest.php — 2 commits
- doc/api.rst — 1 commit
- doc/deprecated.rst — 1 commit
- extra/cache-extra — 1 commit
- extra/markdown-extra — 1 commit
- src/Environment.php — 1 commit
- src/Lexer.php — 1 commit
Notable commits
- fix: Deprecate calling TemplateWrapper::unwrap() without arguments as of 3.30 and list the fix in the CHANGELOG
- fix: Fix IntlExtension inheriting values derived by ICU from a date formatter prototype
- fix: Fix Stringable keys for ArrayAccess implementations
- fix: Fix Traversable sequence destructuring semantics
- fix: Fix TemplateWrapper::hasBlock() and TemplateWrapper::getBlockNames() omitting environment globals
- fix: Fix an empty destructuring pattern triggering a PHP fatal error instead of a SyntaxError
- fix: Fix array access with a Stringable key on subclasses of ArrayObject and ArrayIterator
- fix: Fix array destructuring from a Traversable
- fix: Fix coding standards
- fix: Fix duplicate macro deprecation wording
- fix: Fix html_attr dropping style declarations whose value is zero
- fix: Fix repeated object destructuring evaluation
- fix: Fix split trailing newline
- fix: Fix the default filter fallback reusing a null-safe temporary variable
- fix: Fix the empty comment "{##}" being lexed as a documentation comment opening
- fix: Fix the html_attr documentation about iterables in data attributes
- fix: Fix wrapping the Twig cache pool in a second tag aware adapter
- fix: Merge overlapping CHANGELOG entries for the destructuring fatal error fix
- fix: Strengthen the default filter regression test
- fix: bug #4891 Fix the empty comment "{##}" being lexed as a documentation comment opening (Amoifr)
- …and 108 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
twigphp/Twig was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 2904612341ce968c83a55c07e5b3c92b4499ab5b — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-a15879f6f801.