konradmichalik / typo3-file-sync
File Sync - Synchronizes missing files between TYPO3 instances using configurable resource handlers.
Package info
github.com/konradmichalik/typo3-file-sync
Type:typo3-cms-extension
pkg:composer/konradmichalik/typo3-file-sync
Requires
- php: ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0
- ext-gd: *
- doctrine/dbal: ^4.0
- guzzlehttp/guzzle: ^7.0
- psr/event-dispatcher: ^1.0
- psr/http-client: ^1.0.3
- psr/http-message: ^1.0 || ^2.0
- psr/log: ^3.0.1
- symfony/console: ^7.0
- typo3/cms-backend: ^13.4 || ^14.0
- typo3/cms-core: ^13.4 || ^14.0
Requires (Dev)
- eliashaeussler/version-bumper: ^2.4 || ^3.0
- phpunit/phpunit: ^10.2 || ^11.0 || ^12.0
- typo3/cms-filelist: ^13.4 || ^14.0
Suggests
- typo3/cms-filelist: Show sync status badge in Filelist module
README
TYPO3 extension typo3_file_sync
A lightweight TYPO3 extension that synchronizes missing files on demand — either by fetching them from a remote instance or by generating local placeholder images. Inspired by filefill, this is a leaner reimplementation with TYPO3 v13 + v14 support and self-contained placeholder generation without external service dependencies.
Note
Multiple resource handlers can be chained per storage. They are processed in order until one successfully delivers the file.
🔥 Installation
Requirements
- TYPO3 >= 13.4
- PHP 8.2+
- PHP extension
ext-gd(for placeholder image generation)
Composer
composer require konradmichalik/typo3-file-sync
Setup
vendor/bin/typo3 extension:setup --extension=typo3_file_sync
⚙️ Configuration
File Sync can be configured in two ways: via the TYPO3 backend (per storage) or via PHP configuration (e.g. in ext_localconf.php or additional.php).
Backend
- Go to the List module and edit a File Storage record
- Enable File Sync and configure the resource handlers
PHP
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['typo3_file_sync']['storages'][1] = [ [ 'identifier' => 'remote_instance', 'configuration' => 'https://production.example.com', ], [ 'identifier' => 'placeholder_image', 'configuration' => '#CCCCCC, #969696', ], ];
The array key (1) is the UID of the file storage.
✨ Resource Handlers
Remote Instance
Fetches missing files from a remote TYPO3 instance via HTTP(S). A HEAD request checks existence before downloading; the file path is appended to the configured base URL.
'identifier' => 'remote_instance', 'configuration' => 'https://production.example.com',
Basic Auth
If the remote instance is protected by .htaccess or similar, credentials can be included in the URL:
https://user:password@production.example.com
For environment variable support (works in both backend and PHP configuration), use %env()% placeholders:
https://%env(REMOTE_USER)%:%env(REMOTE_PASS)%@production.example.com
Placeholder Image
Generates local placeholder images with configurable colors. Supports GD-based formats (jpg, png, gif, webp, avif) and svg.
'identifier' => 'placeholder_image', 'configuration' => '#CCCCCC, #969696', // backgroundColor, textColor
The generated image displays the original file dimensions as a text overlay (e.g. 1920 x 1080).
Tip
Chain both handlers to get real assets from production when available, falling back to a placeholder when they are not.
💡 CLI Commands
Reset missing-file flags
Resets the missing flag on sys_file records for all enabled storages or a specific one:
vendor/bin/typo3 file-sync:reset vendor/bin/typo3 file-sync:reset --storage=1
Delete synced files
Removes files previously fetched by File Sync, optionally filtered by handler or storage:
vendor/bin/typo3 file-sync:delete --all vendor/bin/typo3 file-sync:delete --identifier=remote_instance vendor/bin/typo3 file-sync:delete --identifier=remote_instance --storage=1
Warning
file-sync:delete --all permanently removes all files that were fetched by any handler. Run file-sync:reset afterwards to allow them to be re-synced on next access.
🧩 Custom Resource Handlers
Register a custom handler in your ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['typo3_file_sync']['resourceHandler']['my_handler'] = [ 'title' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:my_handler', 'config' => [ 'label' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:my_handler.config', 'config' => [ 'type' => 'input', ], ], 'handler' => \Vendor\MyExtension\Resource\Handler\MyHandler::class, ];
The handler class must implement RemoteResourceInterface:
use KonradMichalik\Typo3FileSync\Resource\RemoteResourceInterface; use TYPO3\CMS\Core\Resource\FileInterface; class MyHandler implements RemoteResourceInterface { public function __construct(array|string|null $configuration) {} public function hasFile(string $fileIdentifier, string $filePath, ?FileInterface $fileObject = null): bool { // Return true when this handler can provide the file } public function getFile(string $fileIdentifier, string $filePath, ?FileInterface $fileObject = null): string|false { // Return file content as string, or false if unavailable } }
🧑💻 Contributing
Please have a look at CONTRIBUTING.md.
📜 License
This project is licensed under GNU General Public License 2.0 (or later).