Developer reference
Architecture
The extension has three entry points that share the same optimization backend:
- ProcessingMiddleware intercepts frontend requests
matching the
/processed/path and asks the Processor to create a variant on demand. - OptimizeOnUploadListener reacts to PSR-14 file events
(
AfterandFile Added Event After) and delegates to the shared ImageOptimizer service for in-place lossless compression.File Replaced Event - OptimizeImagesCommand and AnalyzeImagesCommand iterate the FAL index from the CLI. Both extend AbstractImageCommand, which provides shared database iteration, progress rendering, and option parsing.
The MaintenanceController provides the backend module for statistics, cleanup, and system-requirement checks.
Directory structure
-
-
-
AbstractImageCommand.php
-
AnalyzeImagesCommand.php
-
OptimizeImagesCommand.php
-
-
-
MaintenanceController.php
-
-
-
ImageProcessedEvent.php
-
VariantServedEvent.php
-
-
-
OptimizeOnUploadListener.php
-
-
-
ProcessingMiddleware.php
-
-
-
ImageManagerAdapter.php
-
ImageManagerFactory.php
-
ImageOptimizer.php
-
ImageReaderInterface.php
-
SystemRequirementsService.php
-
-
Processor.php
-
ProcessorInterface.php
-
-
SourceSetViewHelper.php
-
-
-
-
-
Modules.php
-
-
Icons.php
-
RequestMiddlewares.php
-
Services.yaml
-
Processing middleware
-
class
ProcessingMiddleware -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Middleware\ Processing Middleware
Frontend PSR-15 middleware registered before
typo3/(see Middleware registration). Intercepts every request whose path starts withcms- frontend/ site /processed/and delegates to the \Netresearch\NrImageOptimize\ProcessorInterface implementation. Any other request is passed to the next handler unchanged.
Processor
-
class
ProcessorInterface -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Processor Interface
Contract for the on-demand processor -- declares
generate. The middleware depends on this interface, so integrators can replace the implementation via a Services.yaml alias.And Send (Server Request Interface): Response Interface
-
class
Processor -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Processor
Default implementation. Parses the requested URL (see Variant URL format) to extract path, dimensions, quality, and mode. Loads the original via the
Imageadapter (see ImageManager abstraction), generates the primary variant plus optional WebP / AVIF sidecars, and streams a PSR-7 response back with long-lived cache headers.Reader Interface Key behaviors:
- Rejects path-traversal (
..) sequences at URL parse time, returning HTTP 400. - Clamps
w/hto 1--8192 andqto 1--100. - Uses TYPO3's
Lockto serialize concurrent requests for the same variant; a 503 is returned if the lock can't be acquired within 1 second.Factory - Serves the first non-empty file on disk: the AVIF
sidecar, then the WebP sidecar, then the original
format. The
Acceptheader is not inspected; theskipandWeb P skipquery parameters only suppress sidecar generation.Avif - Dispatches \Netresearch\NrImageOptimize\Event\ImageProcessedEvent after a new variant is written and \Netresearch\NrImageOptimize\Event\VariantServedEvent before the response body is sent.
PSR-14 events
Integrators can subscribe to the processor's lifecycle to collect metrics, trigger cache warming, or apply additional post-processing.
-
class
ImageProcessedEvent -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Event\ Image Processed Event
Dispatched after the processor has written a new variant to disk. Properties (all
public readonly):path(Original string)- Absolute path of the source image.
path(Variant string)- Absolute path of the variant -- the actual served
file may be a
.webpor.avifsidecar of this path. extension(string)- Lowercased extension of the variant (
jpg,png,webp,avif...). target/Width target(Height ?int)- Final clamped dimensions in pixels, or
nullif the URL omitted the value. target(Quality int)- Output quality (1--100).
processing(Mode int)0= cover,1= scale / fit.webp/Generated avif(Generated bool)- Whether the respective sidecar was written alongside.
-
class
VariantServedEvent -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Event\ Variant Served Event
Dispatched immediately before the response body is streamed to the client -- both for fresh variants and for cache hits. Properties:
path(Variant string)- Absolute base path of the variant being served.
extension(string)- Lowercased source extension.
response(Status Code int)- HTTP status code (always 200 in practice).
from(Cache bool)truewhen the response reuses a previously generated file on disk;falsewhen the variant was produced in this request.
Register listeners via Configuration/ or the
per-class # attribute:
services:
Acme\Example\Listener\MetricsListener:
tags:
- name: event.listener
identifier: 'acme.metrics.variant_served'
event: Netresearch\NrImageOptimize\Event\VariantServedEvent
Upload event listener
-
class
OptimizeOnUploadListener -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Event Listener\ Optimize On Upload Listener
PSR-14 listener registered for
AfterandFile Added Event After. Normalizes the file extension, short-circuits unsupported extensions and offline storages, and delegates to \Netresearch\NrImageOptimize\Service\ImageOptimizer.File Replaced Event Re-entrancy guard: keyed by
storageso two storages sharing an identifier (Uid . ':' . identifier /image.in different driver roots) don't block each other, while still catching thejpg replaceloop that the optimizer's own write would otherwise trigger.File () Storage state:
setis applied before delegation and restored to its previous value in aEvaluate Permissions (false) finallyblock so long-running CLI runs don't leak permission state across iterations.
ImageOptimizer service
-
class
ImageOptimizer -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Service\ Image Optimizer
Shared backend used by both the event listener and the CLI commands. Resolves optimizer binaries via
$PATH, with env overrides (OPTIPNG_,BIN GIFSICLE_,BIN JPEGOPTIM_). A set-but-invalid override is authoritative -- the tool is reported unavailable rather than silently falling back toBIN $PATH.$PATHlookups also verifyis_.executable () Public API:
optimize(File Interface $file, bool $strip Metadata = false, ?int $jpeg Quality = null, bool $dry Run = false): array - Run the appropriate tool in place and replace the FAL file when the result shrinks.
analyze(File Interface $file, bool $strip Metadata = false, ?int $jpeg Quality = null): array - Same pipeline, but never writes back.
analyzeHeuristic (File Interface $file, int $max Width = 2560, int $max Height = 1440, int $min Size = 512000): array - Fast estimation from size and resolution. No binary is invoked.
resolveTool For (string $extension): ?array - Tool discovery for callers that want to pre-check.
hasAny Tool (): bool - Quick check whether at least one optimizer is installed.
supportedExtensions (): list<string> - Returns
['png', 'gif', 'jpg', 'jpeg'].
ImageManager abstraction
-
class
ImageManagerFactory -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Service\ Image Manager Factory
Selects the best available Intervention Image driver (Imagick over GD). See Image driver selection for behavior and failure modes.
-
class
ImageReaderInterface -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Service\ Image Reader Interface
Version-agnostic abstraction around Intervention Image's loading API. v3 uses
Image, v4 usesManager:: read () Image; this interface hides that difference so consumers and static analysis see a single stable contract.Manager:: decode ()
-
class
ImageManagerAdapter -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Service\ Image Manager Adapter
Default implementation. Dispatches to whichever method is present on the installed
Image, letting the extension support Intervention ImageManager ^3simultaneously without version-conditional code paths.| | ^4
SystemRequirementsService
-
class
SystemRequirementsService -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Service\ System Requirements Service
Produces the data shown on the System requirements tab of the backend module. Inspects:
- PHP version and loaded extensions (
imagick,gd,fileinfo). - ImageMagick / GraphicsMagick capabilities as reported by Imagick (WebP, AVIF support).
- Intervention Image installed version and the active driver (Imagick or GD).
- TYPO3 version.
- Availability of optional CLI tools (
magick,convert,identify,gm).
Returns a structured array the controller renders into a Fluid template.
CLI commands
-
class
AbstractImageCommand -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Command\ Abstract Image Command
Base class for the image CLI commands. Exposes
parse,Storage Uids Option get,Int Option extract,Uid count,Images iterate(Generator overVia Index sys_rows -- constant memory),file create,Progress build,Label shorten, andLabel format.Mb Gb
-
class
OptimizeImagesCommand -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Command\ Optimize Images Command
Implements
nr:. Delegates to \Netresearch\NrImageOptimize\Service\ImageOptimizer per file and renders a Symfony progress bar with cumulative savings. See Bulk optimize images.image: optimize
-
class
AnalyzeImagesCommand -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Command\ Analyze Images Command
Implements
nr:. Usesimage: analyze Image-- no external tool is invoked. See Analyze optimization potential.Optimizer:: analyze Heuristic ()
SourceSetViewHelper
-
class
SourceSetViewHelper -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ View Helpers\ Source Set View Helper
Fluid ViewHelper that generates
<img>tags withsrcsetattributes for responsive image delivery. Supports both density-based (2x) and width-based responsive srcset modes. See Usage for examples and SourceSetViewHelper for the parameter reference.
MaintenanceController
-
class
MaintenanceController -
- Fully qualified name
-
\Netresearch\Nr Image Optimize\ Controller\ Maintenance Controller
Extbase controller powering the backend module. Three actions:
indexAction - Overview of the processed-images directory: file count, total size, largest files, type distribution.
systemRequirements Action - Renders the data produced by \Netresearch\NrImageOptimize\Service\SystemRequirementsService.
clearProcessed Images Action - Recursively deletes every file under the configured processed-images directory. A flash message reports the freed space.
Module registration (access limited to
system) lives inMaintainer Configuration/.Backend/ Modules. php
Testing
composer ci:test
Individual test commands:
composer ci:test:php:cgl # Code style
composer ci:test:php:lint # PHP syntax
composer ci:test:php:phpstan # Static analysis
composer ci:test:php:unit # PHPUnit tests
composer ci:test:php:rector # Code quality
Build/Scripts/runTests.sh -s unit -p 8.4
Build/Scripts/runTests.sh -s phpstan -p 8.4